/**
 * jQuery1.6.2源代码完全解读
 * 注释约定：
 * 1、##数字：如##89，表示代码有关联，请寻找到关联位置，获得关联代码的定义或其他信息
 * 2、#s数字-e数字：如#s5-e669，表示模块之间的代码，s表示表示开头，e表示结束
 */
(function (window,undefined){
	
	
	//1============================================================================================
	

	/**
	 * 定义并初始化这3个变量，作用有二：
	 * 1：保持与变量名与window对象中的属性名一样，不会有歧义，也不会混淆。
	 * 2：通过“缩短方式”可以在jQuery内随时“快速”访问获得到window对象中的相关信息，例如##157处的代码
	 */
	var document=window.document,
	navigator=window.navigator,
	location=window.location;	
	
	
	//1============================================================================================
	

	/**
	 * 开始啦，jQuery定义开始鸟。
	 */
	var jQuery=(function (){//#s31-e1375：jQuery框架的核心定义开始
		
		
		// 定义一个jQuery的本地副本，局部变量
		var jQuery=function (selector,context){//#s33-e38

			// 实际上 jQuery 对象是  jQuery.fn.init 返回的。jQuery.fn.init的定义位于#s141-e286位置
			return new jQuery.fn.init(selector,context,rootjQuery);
			
		},//#s33-e38
		
		// 声明并初始化本地局部变量
		_jQuery=window.jQuery,
		
		// Map over the $ in case of overwrite
		_$=window.$,
		
		// A central reference to the root jQuery(document)
		rootjQuery,
		
		/**
		 * JS正则表达式基本知识：
		 * 参考网址：http://jamcode.iteye.com/blog/481228
		 * 			http://www.cnblogs.com/deerchao/archive/2006/08/24/zhengzhe30fengzhongjiaocheng.html
		 * 			http://www.cnblogs.com/libinqq/archive/2008/07/31/1257699.html
		 * 			http://deerchao.net/tutorials/regex/regex.htm
		 * 1、格式：pattern为表示正则表达式
		 * 		（1）var reg = /pattern/[gim];//示例：var re = /a/i;//匹配a和A
		 * 		（2）var reg = new RegExp(pattern[,gim]);//示例var re=new RegExp("a","i");//匹配a和A
		 * 2、匹配模式：上面的可选参数
		 * 		g	全文匹配，即继续往下匹配直到字符串结尾，可返回多个匹配结果
		 * 		i	忽略大小写，即不区分大小写
		 * 		m	多行匹配
		 * 3、元字符：
		 * 		需要转义的元字符有：$ ^ * + ? | . = : - ' " ( ) [ ] { } \ / < >等英文字符
		 * 4、常用的表达式：
		 * 		.	匹配除换行符之外的任何一个字符，等价于 IE下[^\n]，非IE下[^\n\r]
		 * 		\d	匹配一个数字字符， 等价于 [0-9]
		 * 		\D	匹配一个非数字字符，等价于 [^0-9]
		 * 		\w	匹配任意一个字母或数字或下划线，等价于 "[A-Za-z0-9_]"
		 * 		\W	匹配除字母、数字、下划线之外的字符，等价于 "[^A-Za-z0-9_]"
		 * 		\s	匹配任何空白字符, 包括空格、制表符、回车符、换行符、换页符等等. 等价于[\f\n\r\t\v]
		 * 		\S	匹配任何非空白字符. 等价于 [^\f\r\n\t\v]
		 * 		\b	匹配一个单词边界，也就是指单词和空格间的位置。
		 * 		\B	匹配非单词边界，即左右两边都是 "/w" 范围或者左右两边都不是 "/w" 范围时的字符缝隙
		 * 		\n	换行符
		 * 		\r	回车符
		 * 		\t	制表符
		 * 		\f	换页符（Tab）
		 * 		\cX	与X对应的控制字符
		 * 		\v	垂直制表符
		 * 		\0	空字符("")
		 * 		\0nn	ASCII代码中八进制代码为nn的字符
		 * 		\xnn	ASCII代码中十六进制代码为nn的字符
		 * 		\unnnn	Unicode代码中十六进制代码为nnnn的字符
		 */
		
		//快速匹配表达式，匹配：
		//（1）：匹配HTML字符串，即：以非<开头和非>结束（可选，可任意多个），中间必须包含<和>符号，并且<和>之间必须包含至少一次的“\w”和“\W”。匹配示例：var a="ab<br>cd"
		//（2）：匹配ID字符串，即：以#开头，其后接任意的"\w"和"-"符号的组合。匹配示例：var a="#ab-cd"
		quickExpr=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,//##89，正则表达式中的“?:”的含义可参考：http://zhidao.baidu.com/question/224303126.html
		
		//匹配“非空白字符”。
		rnotwhite=/\S/,
		
		trimLeft=/^\s+/,//匹配“左边的空白字符”
		trimRight=/\s+$/,//匹配“右边的空白字符”
		
		//匹配一个"数字"
		rdigit=/\d/,
		
		//匹配空的单个tag标签：以<开头和>结束，其后接任意"\w"组合的tag标签，然后接关闭的tag标签。示例：var a="<abcd/>",b="<abcd></abcd>"等
		rsingleTag=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,
		
		// JSON相关的正则表达式
		rvalidchars = /^[\],:{}\s]*$/,//匹配任意的“],:{}”和“空白字符”的组合。
		//匹配：\"、\\、\/、\b、\f、\n、\r、\t和\u[0-9a-fA-F]{4}等，全局匹配，示例：var a="\\u5555"
		rvalidescape=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
		//匹配：字符"和"中间除了"、\、/、\n、\t等之外的字符串，或true、false、null、正负数、科学计数格式的正负数等，全局匹配。示例：var a = "\"\/\"",b="true",c="null",d="10.25";等
		rvalidtokens=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
		//匹配：以^、:、,中的任一个符号，其后接任意个\s或[，但至少出现一次。示例：var a=": [",b=",[";等
		rvalidbraces=/(?:^|:|,)(?:\s*\[)+/g,//#mybug，感觉此表达式有误，应该是rvalidbraces=/(?::|,)(?:\s*\[)+/g或rvalidbraces=/(?:\^|:|,)(?:\s*\[)+/g
		
		// 浏览器内核相关的正则表达式，用于获得客户端浏览器的相关信息
		rwebkit=/(webkit)[\/]([\w.]+)/,
		ropera=/(opera)(?:.*version)?[\/]([\w.]+)/,
		rmsie=/(msie)([\w.]+)/,
		rmozilla=/(mozilla)(?:.*?rv:([\w.]+))?/,
		
		// Matches dashed string for camelizing
		rdashAlpha=/-([a-z])/ig,//匹配：符号-后接一个大小字母的字符串，全局匹配且不区分大小写。示例：var a="-S"等。
		
		// Used by jQuery.camelCase as callback to replace()
		fcamelCase=function (all,letter){
			
			return letter.toUpperCase();//全部转为大写
			
		},
		
		// 用于获取客户端浏览器的相关信息
		userAgent=navigator.userAgent,
		
		// 用于匹配浏览器的引擎（内核）和版本
		browserMatch,
		
		// The deferred used on DOM ready // DOM解析时使用此变量，缓存DOM ready事件
		readyList,
		
		// The ready event handler // 处理DOM ready加载事件的事件，当DOM加载完成时执行
		DOMContentLoaded,
		
		// 保存一些JS核心方法的引用，下面会经常用到这些方法
		toString = Object.prototype.toString ,
		// ##142，Object的原型方法，是用来判断一个对象是否有你给出名称的属性或对象。详解参见：http://kevinpeng.iteye.com/blog/766755或http://www.cnblogs.com/jenry/archive/2010/12/08/1900150.html
		hasOwn = Object.prototype.hasOwnProperty ,
		//##143，数组的原型方法，向数组的末尾添加一个或更多元素，并返回新的长度。详解参见：http://www.iteye.com/topic/764850
		push = Array.prototype.push ,
		//##144，数组的原型方法，从某个已有的数组中截取数组中的一部分，并返回一个新数组，通常用它来复制数组。详解参见：http://www.iteye.com/topic/764850
		slice=Array.prototype.slice,
		//##148，String的原型方法，用于去除字符串的头尾空格。注意：String类型本身并没有trim方法，但允许客户端用户自定义添加原型trim方法。
		trim=String.prototype.trim,
		//##151，Array的原型方法，用于搜索数组中元素。注意：Array类型本身并没有indexOf方法，但允许客户端用户自定义添加原型indexOf方法。
		indexOf=Array.prototype.indexOf,
		
		// [[Class]] -> type pairs //对象与类型之间的映射对，这里现在只是“空壳”，后面会填充内容，参见##1451位置的代码
		class2type={
				
		};

		/**
		 * 重要：定义jQuery的原型，
		 * 这里的jQuery.fn相当于jQuery.prototype的别名，方便以后使用，它们指向同一个引用
		 */
		jQuery.fn=jQuery.prototype={//#s131-e351
				
			//定义构造器调用的函数，其实还是调用了下面的init方法，见##30处的代码
			constructor :jQuery,

			/**
			 * jQuery的核心函数。实现了jQuery的多种动态调用功能
			 * @param {Object} selector 选择器
			 * @param {Object} context 上下文
			 * @param {Object} rootjQuery 父节点
			 */
			init:function (selector,context,rootjQuery){//#s141-e286
				
				var match,elem,ret,doc;
				
				// 处理这些调用： $(""), $(null), $(false)或 $(undefined)。示例：alert(jQuery(""));等
				if(!selector){//#mybug，我觉得这里有不足，应该为：!selector||(typeof selector==="string"&&/^\s*$/.test(selector))
					
					return this;//直接返回jQuery对象本身，此时jQuery对象是一个空对象（空数组），即[]
					
				}

				// 处理选择器是DOM元素对象的调用： $(DOMElement)。
				/**
				 * 在WEB页面加载时，首先会以jQuery(document)方式调用这里初始化jQuery对象。参见##1405的代码。对于document，其nodeType属性为9，见下面的扩展知识讲解。
				 * 扩展知识：
				 * 		nodeType属性可返回节点的类型，常见的有：1-元素element，2-属性attr，3-文本text，8-注释comments，9-文档document。
				 * 	关于nodeType属性的详细讲解，参见：
				 * 		http://www.cnblogs.com/sweting/archive/2009/12/06/1617839.html，
				 * 		http://www.impng.com/web-dev/element-nodetype-values.html，
				 * 		http://blog.csdn.net/ppjava2009/article/details/5323177
				 */
				if(selector.nodeType){//示例：var a= {nodeType:"mynode",length:0,splice:[].splice}; jQuery(a);
					
					this.context=this[0]=selector;//直接将参数（即选择器）放到jQuery对象的0位置，并且赋给上下文
					this.length=1;//将jQuery对象的大小设置为1
					return this;//返回jQuery对象
					
				}
				
				// 处理选择器是body的调用：$("body")，一旦发现body存在一次，优先查询
				if(selector==="body"&&!context&&document.body){//示例：jQuery("body");
					
					this.context=document;//##157，将上下文设置为整个document文档
					this[0]=document.body;//直接将document.body放到jQuery对象的0位置
					this.selector=selector;
					this.length=1;
					return this;
					
				}

				// 处理$(HTML代码或者css选择器)的调用：$(string)，如：$("<p>test</p>")或$("#myid")等
				if(typeof selector==="string"){//#s186-e293

					// 判断选择器是否为HTML标签或ID：选择器selector以<开头和>结尾，且长度大于等于3。
					if(selector.charAt(0)==="<"&&selector.charAt(selector.length-1)===">"&&selector.length>=3){

						// 若选择器的开始和结束就是<和>字符，那就是HTML标签，跳过正则表达式检查
						match=[null,selector,null];//示例结果：match=[null,"<p>test</p>",null];
						
					}else {//示例：jQuery("ab<p>test</p>cd");或jQuery("#ab-cd");
						
						//调用正则表达式，关于quickExpr的作用见##89，若匹配正则表达式不成功，则match=null;
						match=quickExpr.exec(selector);//示例结果：match=["ab<p>test</p>cd","<p>test</p>",undefined];或match=["#ab-cd",undefined,"ab-cd"];
						
						//由匹配结果可知：match[0]==selector本身，match[1]==selector内含的tab标签，match[2]==#ID中的ID		
						
					}

					// match不为空，上面的判断或正则表达式匹配成功了
					if(match&&(match[1]||!context)){//#s203-e276

						// 处理标签的调用: $(html) -> $(array)
						if(match[1]){//match[1]不为空，此时selector选择器是一个tag标签
							
							//若context为jQuery类型的实例，设置context为context[0]，否则为本身
							context=context instanceof jQuery?context[0]:context;
							//context未初始化时，设置doc为document，否则，判断context.ownerDocument是否存在，若存在,设置doc为context.ownerDocument，否则设置doc为context。
							doc=(context?context.ownerDocument||context:document);
							
							//判断选择器是否是一个空的tag标签（单一标签），只做createElement，并跳过其余动作
							//关于rsingleTag的作用见##86，若匹配正则表达式不成功，则ret=null;
							ret=rsingleTag.exec(selector);//匹配示例：jQuery("<br/>");或jQuery("<br></br>");匹配结果：ret=["<br/>","br"]或ret=["<br></br>","br"]
							
							//由匹配结果可知：ret[0]==selector本身，ret[1]==标签名					
							
							if(ret){//此时true表示选择器selector是空的tag标签。示例：jQuery("<br/>");或jQuery("<br></br>");
								
								//判断上下文是否是一个"纯粹"的Object对象，isPlainObject参见#s800-e838位置的代码
								if(jQuery.isPlainObject(context)){
									
									selector=[document.createElement(ret[1])];//ret[1]为标签名，createElement并返回给selector
									jQuery.fn.attr.call(selector,context,true);//参见#s2898-e2902处的代码
									
								}else {
									
									selector=[doc.createElement(ret[1])];//ret[1]为标签名，createElement并返回给selector
									
								}
								
								
							}else {//此时false表示选择器selector不是空的tag标签。示例：jQuery("<p>test</p>");或jQuery("<abcd>1234</abcd>");等
								
								//在doc中创建片段代码match[1]，buildFragment见#s9040-e9107
								ret=jQuery.buildFragment([match[1]],[doc]);
								
								selector=(ret.cacheable?jQuery.clone(ret.fragment):ret.fragment).childNodes;							
								
							}

							//将此选择器（即标签）合并入jQuery对象中
							return jQuery.merge(this,selector);							
							
						// 处理ID调用: $("#id")
						}else {
							
							elem=document.getElementById(match[2]);//由上面的匹配结果可知，match[2]==#ID中的ID					
							
							// Check parentNode to catch when Blackberry 4.6 returns
							// nodes that are no longer in the document #6963
							if(elem&&elem.parentNode){
								
								// Handle the case where IE and Opera return items
								// by name instead of ID
								//处理在IE和Opera中，会以by name代替by ID的方式返回对象的问题。
								if(elem.id!==match[2]){
									
									return rootjQuery.find(selector);									
									
								}

								
								// Otherwise, we inject the element directly into the
								// jQuery object
								this.length=1;//将jQuery对象的大小设置为1
								this[0]=elem;//直接获得的elem放到jQuery对象的0位置
								
							}

							
							this.context=document;//##157，将上下文设置为整个document文档
							this.selector=selector;							
							return this;
							
						}
						
					} //#s203-e276
					
					// 处理: $(expr, $(...))
					else if(!context||context.jquery){
						
						return (context||rootjQuery).find(selector);						
						
					// 处理: $(expr, context)
					// 这只是相当于：$(上下文).find(表达)。
					}else {
						
						return this.constructor (context).find(selector);						
						
					}
					
				} //#s186-e293
				
				// 处理: $(function)
				// Shortcut for document ready
				else if(jQuery.isFunction(selector)){//isFunction见##739，用于判断selector是否为Function。
					
					return rootjQuery.ready(selector);//ready函数见#s417-e427
					
				}

				
				if(selector.selector!==undefined){
					
					this.selector=selector.selector;					
					this.context=selector.context;					
					
				}

				
				return jQuery.makeArray(selector,this);				
				
			},//#s141-e286
			
			// 开始于一个空的选择器。示例：alert(jQuery.fn.selector);
			selector:"",
			
			// 当前使用的jQuery版本。示例：alert(jQuery.fn.jquery);
			jquery:"1.6.2",
			
			// jQuery对象默认的长度为0
			length:0,
			
			// 匹配集体中包含的元素个数。示例：alert(jQuery.fn.size());
			size:function (){
				
				return this.length;				
				
			},
			
			//转化为数组：对数组进行复制和排序，并返回复制后的新数组
			toArray:function (){//##358
				
				//slice()是数组(Array)原型的方法，格式：slice(start,[end])，该方法返回一个新数组，包含了源函数从start到 end所指定的元素
				return slice.call(this,0);//相当于this.slice(0);
				
			},
			
			// Get the Nth element in the matched element set OR
			// Get the whole matched element set as a clean array
			// 获得元素集合中的第N个元素（若num为null则先对集合进行排序）
			get:function (num){
				
				return num==null?
				
				// Return a 'clean' array //参见##358
				this.toArray():
				
				// Return just the object //返回指定位置的元素
				(num<0?this[this.length+num]:this[num]);				
				
			},
			
			// Take an array of elements and push it onto the stack
			// (returning the new matched element set)
			// 从elems中取出元素，并推入堆栈中，最后返回新的集合，即返回推栈后的集合
			pushStack:function (elems,name,selector){
				
				// Build a new jQuery matched element set
				// 构建并返回新的jQuery元素集合
				var ret=this.constructor ();				
				
				if(jQuery.isArray(elems)){
					
					push.apply(ret,elems);//相当于:for(var i=0;i<elems;i++){ret.push(elems[i]);}	
					
				}else {
					
					//将elems合并到ret中，merge参见#s1127-e1156
					jQuery.merge(ret,elems);
					
				}

				
				// Add the old object onto the stack (as a reference)
				// 添加旧对象到堆栈（作为引用）
				ret.prevObject=this;				
				
				ret.context=this.context;				
				
				if(name==="find"){
					
					ret.selector=this.selector+(this.selector?" ":"")+selector;					
					
				}else if(name){
					
					ret.selector=this.selector+"."+name+"("+selector+")";					
					
				}

				
				// Return the newly-formed element set //返回新的集合，即返回推栈后的集合
				return ret;				
				
			},
			
			// Execute a callback for every element in the matched set.
			// (You can seed the arguments with an array of args, but this is
			// only used internally.)
			// 遍历集合的每一个元素，回调：args参数被作为数组，但仅在内部使用
			each:function (callback,args){
				
				return jQuery.each(this,callback,args);//参见#s978-s1048
				
			},
			
			//注册fn函数到DOM Ready事件，可参考：http://www.cnblogs.com/zhangziqiu/archive/2011/06/27/DOMReady.html
			ready:function (fn){//#s417-e427
				
				// Attach the listeners //绑定到ready事件中
				jQuery.bindReady();				
				
				// Add the callback //添加fn函数到readyList队列中，此时还没有执行fn函数
				readyList.done(fn);				
				
				return this;
				
			},//#s417-e427
			
			//获得jQuery对象的第i个元素
			eq:function (i){
				
				//i等于-1时，返回最后一个元素，否则返回第i个元素（下标从0开始）
				return i===-1?
				this.slice(i):
				this.slice(i,+i+1);				
				
			},
			
			//获得jQuery对象的第0个元素
			first:function (){
				
				return this.eq(0);				
				
			},
			
			//获得jQuery对象的最后一个元素
			last:function (){
				
				return this.eq(-1);				
				
			},
			
			slice:function (){
				
				return this.pushStack(slice.apply(this,arguments),
				"slice",slice.call(arguments).join(","));				
				
			},
			
			map:function (callback){
				
				return this.pushStack(jQuery.map(this,function (elem,i){
					
					return callback.call(elem,i,elem);					
					
				}));				
				
			},
			
			end:function (){
				
				return this.prevObject||this.constructor (null);				
				
			},
			
			// 以下三个方法仅供jQuery内部使用，使用的是Array数组的原型方法，而不是jQuery方法。
			push:push,//push为Array数组的原型方法，参见##143，或详解参见：http://www.iteye.com/topic/764850
			//sort为Array数组的原型方法，用于数组元素排序（默认为升序排序），详解参见：http://www.iteye.com/topic/764850
			sort:[].sort,
			// splice为Array数组的原型方法，详解参见：http://www.iteye.com/topic/764850
			splice:[].splice 
			
		};
		
		/**
		 * 重要：设置jQuery的init函数的原型为jQuery.fn的实例。
		 * 由#s33-e38可知，jQuery实例为init函数返回的实例，
		 * 另，由#s131-e351可知，jQuery.fn为jQuery 原型的别名引用，
		 * 结合这里可知，init函数的原型又被设置为jQuery原型，即init函数原型==jQuery原型。
		 */
		jQuery.fn.init.prototype=jQuery.fn;		
		
		/**
		 * 重要：jQuery的插件定义，
		 * 有了此定义之后，后面才可以对jQuery进行插件的扩展实现，
		 * 同理，基于此，客户端才能手动增加其他插件实现。
		 * 
		 * 两种插件扩展的方式：（注意它们的区别），参考地址：http://www.iteye.com/topic/566490、http://www.iteye.com/topic/545971和http://www.cnblogs.com/fromearth/archive/2009/07/08/1519054.html
		 * (1)通过jQuery.extend扩展（自身扩展、静态扩展）：
		 * 		这种方式相当于为jQuery添加静态方法。静态方法是不需要new一个实例再去调用的，通过“类名+方法名”直接调用(即jQuery.方法名)。例如：#s586-e1365处的代码块就是通过这种方式为jQuery添加静态方法的。
		 * 		因此，jQuery中的isFunction, isArray, trim等都是静态方法，只能通过$.isFunction, $.isArray, $.trim来调用。而不能通过$("...").isFuction, $("...").isArray, $("...").trim调用。
		 * (2)通过jQuery.fn.extend扩展（原型扩展、对象扩展）：
		 * 		这种方式是在jQuery原型上进行插件扩展。因此扩展的属性或方法都添加到jQuery对象上了。例如：#s2779-e3121和#s5241-e5350处的代码块都是通过这种方式为jQuery原型扩展插件的。
		 * 		因此，如attr, prop, bind, one, unbind等可以通过$("...").attr, $("...").prop, $("...").bind, $("...").one, $("...").unbind方式调用。却不能通过$.attr, $.prop, $.bind, $.one, $.unbind方式调用。
		 * 
		 * 为便于理解上面两种方式的区别，请看下面两种方式的不同：
		 * (1)
		 	<pre>
		 		function fun(){}//定义一个类（函数）
		 		
		 		//为该类（函数）添加一个静态方法extend
		 		fun.extend=function(obj){
		 			for(var a in obj)
		 				this[a] = obj[a];//注意：这里的this即fun
		 		}
		 		
		 		//调用extend为该类添加了静态属性name，静态方法method1
		 		fun.extend({name:"fun",method1:function(){}});
		 		
		 		//输出extend,method1,prototype
		 		console.dir(fun)
		  	</pre>
		 * (2)
		 	<pre>
		 		function fun(){}//定义一个类（函数）
		 		
		 		//给该类原型上添加一个方法extned
		 		fun.prototype.extend = function(obj){
		 			for(var a in obj)
		 				this[a] = obj[a];//注意：这里的this即是fun.prototype
		 		}
		 		
		 		//调用extend方法给fun.prototype上添加属性，方法
		 		fun.prototype.extend({name:"fun2",method1:function(){}})
		 		
		 		//输出name,extend,method1,__proto__
		 		console.dir(new fun())
		  	</pre>
		 */
		// jQuery.fn = jQuery.prototype
		// jQuery.fn.extend = jQuery.prototype.extend
		jQuery.extend=jQuery.fn.extend=function (){//#s483-e583
			
			//options：用于在复制时记录参数对象
			//name：用于在复制时记录对象属性名
			//src：用于在复制时记录目标对象的属性值
			//copy：用于在复制时记录参数对象的属性值
			//copy：用于在复制时记录参数对象的属性值
			var options,name,src,copy,copyIsArray,clone,
			
			//目标对象，此方法的末尾返回的就是这个目标对象
			target=arguments[0]||{},
			//循环变量，它会在循环时指向需要复制的第一个对象的位置，默认为1，如果需要进行深度复制，则它指向的位置为2
			i=1,
			//实参长度
			length=arguments.length,
			//是否进行深度拷贝  
		    //深度拷贝情况下，会对对象更深层次的属性对象进行合并和覆盖
			deep=false;			
			
			// 处理：深度COPY，当target（即arguments[0]）为boolean类型时。即：只有当第一个实参为true时,即需要进行深度拷贝时,执行以下if代码块
			if(typeof target==="boolean"){
				
				//deep = true,进行深度拷贝
				deep=target;
				
				//进行深度拷贝时目标对象为第二个实参,如果没有则默认为空对象
				target=arguments[1]||{};
				
				// skip the boolean and the target
				//因为有了deep深度复制参数,因此i指向的位置为第二个参数
				i=2;				
				
			}

			
			// Handle case when target is a string or something (possible in deep copy)
			// 处理：当target为字符串类型或其他类型（深度COPY下），即target不是object类型且不是function类型时。
			if(typeof target!=="object"&&!jQuery.isFunction(target)){
				
				target={};				
				
			}

			
			// extend jQuery itself if only one argument is passed
			// 如果只有一个参数，扩展jQuery本身，即length等于1 时，设置target为jQuery本身
			if(length===i){
				
				//target = this;这句代码是整个extend函数的核心  
		        //在这里目标对象被更改,这里的this指向调用者
		        //在 $.extend()方式中表示jQuery对象本身  
		        //在 $.fn.extend()方式中表示jQuery函数所构造的对象(即jQuery类的实例) 
				target=this;
				
				//自减1,便于在后面的拷贝循环中,可以指向需要复制的对象
				--i;				
				
			}

			//循环实参,循环从第1个参数开始,如果是深度复制,则从第2个参数开始
			for(;i<length;i++){
				
				// Only deal with non-null/undefined values //只处理不为null和undefined的值
				//当前参数不为null,undefined,0,false,空字符串时  
		        //options表示当前参数对象
				if((options=arguments[i])!=null){
					
					// Extend the base object
					//遍历当前参数对象的属性,属性名记录到name
					for(name in options){
						
						src=target[name];//src用于记录目标对象中的当前属性值						
						copy=options[name];//copy用于记录参数对象中的当前属性值
						
						// Prevent never-ending loop //防止进入死循环
						//存在目标对象本身的引用,构成死循环,结束此次遍历
						if(target===copy){
							
							continue;
							
						}
						
						// Recurse if we're merging plain objects or arrays //递归调用，如果我们合并纯对象或数组
						//如果需要进行深度拷贝,且copy的类型为对象或数组
						if(deep&&copy&&(jQuery.isPlainObject(copy)||(copyIsArray=jQuery.isArray(copy)))){
							
							if(copyIsArray){
								
								copyIsArray=false;
								//如果src的类型为数组,则clone记录src，否则colne设为一个空数组
								clone=src&&jQuery.isArray(src)?src:[];
								
							}else {
								
								//如果src的类型为对象,则clone记录src，否则colne设为一个空对象
								clone=src&&jQuery.isPlainObject(src)?src:{};								
								
							}

							
							// Never move original objects, clone them //不移动原始对象，直接克隆他们
							//对copy迭代深度复制
							target[name]=jQuery.extend(deep,clone,copy);							
							
							// Don't bring in undefined values
							
						}else if(copy!==undefined){//如果不需要进行深度拷贝
							
							//直接将copy复制给目标对象
							target[name]=copy;
							
						}
						
					}
					
				}
				
			}

			
			// Return the modified object //返回改变后了的target对象
			//最后返回处理后的目标对象
			return target;
			
		};	//#s483-e583
		
		/**
		 * 重要：jQuery的插件实现的第一种方式（静态扩展方式），客户端手动增加其他插件时，可参考这里的实现格式。
		 * 格式：
		 * 		（1）定义格式：jQuery.extend({插件名1:插件实现1, 插件名2:插件实现2...});
		 * 		（2）调用格式：jQuery.插件名(args)，或者$.插件名(args)
		 * 示例：
		 * 		（1）定义示例：jQuery.extend({min:function(a,b){return a<b?a:b;},max:function(a,b){return a>=b?a:b;}});
		 * 		（2）调用示例：上面定义插件示例分别为返回两者中的小者和大者。alert(jQuery.min(3,5));alert(jQuery.max(3,5));
		 */
		jQuery.extend({//#s586-e1365
			
			//通过jQuery.noConflict()方法将变量$的控制权让渡给其他库，可解决jQuery与其他库的冲突，详解参见：http://www.iteye.com/topic/566090
			noConflict:function (deep){
				
				if(window.$===jQuery){
					
					window.$=_$;					
					
				}

				
				if(deep&&window.jQuery===jQuery){
					
					window.jQuery=_jQuery;					
					
				}

				
				return jQuery;				
				
			},
			
			// Is the DOM ready to be used? Set to true once it occurs.
			// DOM就绪好了吗？一旦就绪好，就设置为true。初始默认为false，即DOM还没就绪好
			isReady:false,
			
			// A counter to track how many items to wait for before
			// the ready event fires. See #6781
			//用一个记数器标记有多少个DOM ready事件需要触发执行
			readyWait:1,
			
			// Hold (or release) the ready event //保持（或释放）ready事件
			holdReady:function (hold){
				
				if(hold){
					
					jQuery.readyWait++;					
					
				}else {
					
					jQuery.ready(true);					
					
				}
				
			},
			
			// Handle when the DOM is ready //处理DOM载入就绪时要执行的函数（已经在前面的#s417-e427中，将待处理函数添加到readyList队列中）
			ready:function (wait){//#s681-e709
				
				// Either a released hold or an DOMready/load event and not yet ready
				if((wait===true&&!--jQuery.readyWait)||(wait!==true&&!jQuery.isReady)){
					
					// Make sure body exists, at least, in case IE gets a little
					// overzealous (ticket #5443).
					// 若不存在document.body，每1毫秒执行一次jQuery.ready函数，即#s681-e709的函数
					if(!document.body){
						
						return setTimeout(jQuery.ready,1);						
						
					}

					
					// Remember that the DOM is ready //设置DOM已经就绪好
					jQuery.isReady=true;					
					
					// If a normal DOM Ready event fired, decrement, and wait if need be
					// 如果已经执行了一个正常的DOM Ready事件，则将readyWait递减
					if(wait!==true&&--jQuery.readyWait>0){
						
						return ;						
						
					}

					
					// If there are functions bound, to execute
					// 如果发现有DOM Ready事件，逐个执行（Ready事件已经在前面的#s417-e427中，将待处理函数添加到readyList队列中）
					readyList.resolveWith(document,[jQuery]);//立刻执行readyList中的所有函数
					
					// Trigger any bound ready events //触发所有绑定的Ready事件，触发完成之后解除绑定
					if(jQuery.fn.trigger){
						
						jQuery(document).trigger("ready").unbind("ready");
						
					}
					
				}
				
			},//#s681-e709
			
			// 封装：添加监听函数，绑定（注册、创建）的DOM Ready事件
			// 可参考：http://www.cnblogs.com/zhangziqiu/archive/2011/06/27/DOMReady.html和http://www.cnblogs.com/rubylouvre/archive/2009/08/26/1554204.html
			bindReady:function (){
				
				if(readyList){
					
					return ;					
					
				}

				
				readyList=jQuery._Deferred();				
				
				// Catch cases where $(document).ready() is called after the
				// browser event has already occurred.
				if(document.readyState==="complete"){// 判断document是否加载完成，参见：http://www.cnblogs.com/lhb25/archive/2009/07/30/1535420.html
					
					// Handle it asynchronously to allow scripts the opportunity to
					// delay ready
					return setTimeout(jQuery.ready,1);
					
				}

				
				// Mozilla, Opera and webkit nightlies currently support this event
				if(document.addEventListener){//Mozilla、Opera和webkit等浏览器
					
					// Use the handy event callback
					//注册DOMContentLoaded事件，用于设置DOM加载完成时执行DOMContentLoaded函数，即##s1455的函数。
					document.addEventListener("DOMContentLoaded",DOMContentLoaded,false);//DOMContentLoaded是Mozillat等浏览器下特有的Event, 当所有DOM解析完以后会触发这个事件。参见：http://wayne173.iteye.com/blog/906030
					
					// A fallback to window.onload, that will always work
					window.addEventListener("load",jQuery.ready,false);
					
					// If IE event model is used
					
				}else if(document.attachEvent){//IE浏览器
					
					// ensure firing before onload,
					// maybe late but safe also for iframes
					document.attachEvent("onreadystatechange",DOMContentLoaded);//注册DOMContentLoaded事件，用于设置DOM加载完成时执行DOMContentLoaded函数，即##s1465的函数。
					
					// A fallback to window.onload, that will always work
					window.attachEvent("onload",jQuery.ready);					
					
					// If IE and not a frame
					// continually check to see if the document is ready
					var toplevel=false;					
					
					try{
						
						toplevel=window.frameElement==null;						
						
					}catch(e){
						
					}

					
					if(document.documentElement.doScroll&&toplevel){
						
						doScrollCheck();						
						
					}
					
				}
				
			},
			
			// See test/unit/core.js for details concerning isFunction.
			// Since version 1.3, DOM methods and functions like alert
			// aren't supported. They return false on IE (#2968).
			//判断obj对象是否完全是一个Function函数对象。从1.3版本起，不再支持DOM方法和函数，如alert等，他们都将返回false。
			//示例：var a=function(){};alert(jQuery.isFunction(a));
			isFunction:function (obj){//##739
				
				return jQuery.type(obj)==="function";				
				
			},
			
			//判断obj对象是否完全是一个集合对象。示例：var a=[1];alert(jQuery.isArray(a));
			isArray:Array.isArray||function (obj){//##757
				
				return jQuery.type(obj)==="array";				
				
			},
			
			// A crude way of determining if an object is a window
			// 使用一种极端的方式判断参数obj是否为window对象。示例：alert(jQuery.isWindow(window));
			isWindow:function (obj){
				
				return obj&&typeof obj==="object"&&"setInterval" in obj;				
				
			},
			
			//判断obj对象是否为非数字对象。示例：var a="abc";alert(jQuery.isNaN(a));
			isNaN:function (obj){
				
				return obj==null||!rdigit.test(obj)||isNaN(obj);				
				
			},
			
			//用于获得obj的类型。示例：var a="abc";alert(jQuery.type(a));
			type:function (obj){
				
				return obj==null?
				String(obj):
				class2type[toString .call(obj)]||"object";				
				
			},
			
			/**
			 * 用于判断参数obj是不是“纯”的Object对象，即判断对象否为纯粹的对象字面量。
			 * 对于通过字面量定义的对象和new Object的对象返回true，而对于任何new Object时传参数和其他的对象都返回false。
			 * 参考地址：http://www.cnblogs.com/phpmix/articles/1733599.html和http://www.iteye.com/topic/663245。
			 * 示例：
			 * jQuery.isPlainObject({}); // true，字面量对象
			 * jQuery.isPlainObject({a:"abc",b:123,c:function(){}}); // true，字面量对象
			 * jQuery.isPlainObject(new Object()); // true
			 * jQuery.isPlainObject(new Object(null)); // true
			 * jQuery.isPlainObject(new Object(undefined)); // true
			 * jQuery.isPlainObject(null); // false
			 * jQuery.isPlainObject(undefined); // false
			 * jQuery.isPlainObject(""); // false
			 * jQuery.isPlainObject(123); // false
			 * jQuery.isPlainObject("test"); // false
			 * jQuery.isPlainObject(new Object("test")); // false
			 * jQuery.isPlainObject(其他); // false
			 * 
			 * @param {Object} obj
			 */
			isPlainObject:function (obj){//#s800-e838
				
				// Must be an Object.
				// Because of IE, we also have to check the presence of the constructor
				// property.
				// Make sure that DOM nodes and window objects don't pass through, as
				// well
				//必须是Object对象，对于IE浏览器，还需要判断存在构造器属性
				//另，如果是DOM节点或window对象，也返回false
				if(!obj||jQuery.type(obj)!=="object"||obj.nodeType||jQuery.isWindow(obj)){
					
					return false;					
					
				}

				
				// Not own constructor property must be Object
				// 如果不存在构造器属性，则返回false
				if(obj.constructor &&
				!hasOwn.call(obj,"constructor")&&
				!hasOwn.call(obj.constructor .prototype,"isPrototypeOf")){
					
					return false;					
					
				}

				
				// Own properties are enumerated firstly, so to speed up,
				// if last one is own, then all properties are own.
				
				var key;				
				for(key in obj){
					
				}

				
				return key===undefined||hasOwn.call(obj,key);				
				
			},//#s800-e838
			
			//判断obj是否为一个空对象。示例：var a=[],b={};jQuery.isEmptyObject(a);
			isEmptyObject:function (obj){
				
				for(var name in obj){
					
					return false;					
					
				}

				return true;				
				
			},
			
			//抛出异常错误。示例：try{jQuery.error(10/0);}catch(e){alert(e);}
			error:function (msg){
				
				throw msg;
				
			},
			
			//将参数data解析为JSON对象，并返回此JSON对象。示例：var jstr='{"a":1,"b":2}';var jobj=jQuery.parseJSON(jstr);alert(jobj.a);
			parseJSON:function (data){
				
				if(typeof data!=="string"||!data){
					
					return null;					
					
				}

				
				// Make sure leading/trailing whitespace is removed (IE can't handle it)
				data=jQuery.trim(data);//去除头尾的空格			
				
				// Attempt to parse using the native JSON parser first //首先尝试使用原生的JSON解析器（window.JSON这个对象，在Firefox/Webkit的浏览器中存在，但IE6-IE8都没有。）
				if(window.JSON&&window.JSON.parse){
					
					return window.JSON.parse(data);					
					
				}

				
				// Make sure the incoming data is actual JSON
				// Logic borrowed from http://json.org/json2.js
				// 通过正则表达式判断参数data是否符合JSON格式，若符合，返回JSON的对象字面量。
				if(rvalidchars.test(data.replace(rvalidescape,"@")
				.replace(rvalidtokens,"]")
				.replace(rvalidbraces,""))){
					
					
					return (new Function("return "+data))();
					
					
				}

				jQuery.error("Invalid JSON: "+data);//解析出错，抛出异常
				
			},
			
			// Cross-browser xml parsing
			// (xml & tmp used internally)
			// 支持跨浏览器的XML解析：对参数data进行XML解析，并返回解析生成的xml对象。
			// 示例：var xstr="<person><uid>编号</uid><uname>姓名</uname></person>";var xobj=jQuery.parseXML(xstr);alert(xobj.getElementsByTagName("uid")[0].childNodes[0].nodeValue);
			parseXML:function (data,xml,tmp){
				
				
				if(window.DOMParser){//非IE浏览器
					// Standard
					tmp=new DOMParser();// 创建DOM解析器
					xml=tmp.parseFromString(data,"text/xml");					
					
				}else {//IE浏览器
					// 创建DOM解析器
					xml=new ActiveXObject("Microsoft.XMLDOM");					
					xml.async="false";					
					xml.loadXML(data);
					
				}

				
				tmp=xml.documentElement;				
				
				if(!tmp||!tmp.nodeName||tmp.nodeName==="parsererror"){//解析出错，抛出异常
					
					jQuery.error("Invalid XML: "+data);					
					
				}

				
				return xml;
				
			},
			
			noop:function (){
				
			},
			
			// Evaluates a script in a global context
			// Workarounds based on findings by Jim Driscoll
			// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
			// 在全局范围下执行一些动态的JavaScript代码。
			// 示例：jQuery.globalEval("var newVar = function(a,b){return a*b};")alert(newVar(3,5));
			globalEval:function (data){
				
				if(data&&rnotwhite.test(data)){
					
					// We use execScript on Internet Explorer
					// We use an anonymous function so that context is window
					// rather than jQuery in Firefox
					// 在IE中使用execScript方法来执行JS代码，由于Firefox下没有execScript方法，则使用一个匿名函数和window.eval方法一起实现相同的功能
					// 关于window.eval和window.execScript的区别，详解参见：http://www.iteye.com/topic/519098和http://www.cnblogs.com/hust/archive/2011/04/24/2026200.html
					(window.execScript||function (data){
						
						window["eval"].call(window,data);//相当于window.eval(data);
						
					})(data);					
					
				}
				
			},
			
			// Converts a dashed string to camelCased string;
			// Used by both the css and data modules
			// 转换含有中划线（即符号-）的字符串为驼峰字符串，此功能常用于CSS和数据模块或代码之间
			// 示例：var a="font-size";var b=jQuery.camelCase(a);//b=fontSize
			camelCase:function (string){
				
				return string.replace(rdashAlpha,fcamelCase);				
				
			},
			
			// 用于判断参数elem的nodeName属性（即节点名称或标签名称）是否与参数name相同（不区分大小写），若elem不存在nodeName属性返回false
			// 示例：var node=document.getElementById("cba");alert(jQuery.nodeName(node,"input"));//请先body内添加：<input type="text" name="cba" id="cba">
			nodeName:function (elem,name){
				
				return elem.nodeName&&elem.nodeName.toUpperCase()===name.toUpperCase();				
				
			},
			
			// args is for internal usage only //参数args仅在内部使用
			// 用于遍历参数object中的每一个成员/元素，并对每个成员/元素执行回调callback函数。
			// 示例：var person={name:'china',age:25};jQuery.each(person,function(key,value){alert(key+': '+value);});
			each:function (object,callback,args){//#s978-s1048
				
				var name,i=0,
				length=object.length,
				isObj=length===undefined||jQuery.isFunction(object);				
				
				if(args){
					
					if(isObj){
						
						for(name in object){
							
							if(callback.apply(object[name],args)===false){
								
								break;								
								
							}
							
						}
						
					}else {
						
						for(;i<length;){
							
							if(callback.apply(object[i++],args)===false){
								
								break;								
								
							}
							
						}
						
					}

					
					// A special, fast, case for the most common use of each
					
				}else {
					
					if(isObj){
						
						for(name in object){
							
							if(callback.call(object[name],name,object[name])===false){
								
								break;								
								
							}
							
						}
						
					}else {
						
						for(;i<length;){
							
							if(callback.call(object[i],i,object[i++])===false){
								
								break;								
								
							}
							
						}
						
					}
					
				}

				
				return object;				
				
			},//#s978-s1048
			
			// Use native String.trim function wherever possible 
			// 去除字符串头尾的空格：尽可能使用原生String.trim的功能（若存在），否则，使用jQuery自己的实现功能
			// 示例：var a="  abc  ",b=123;alert(jQuery.trim(a)+b);
			trim:trim?
			function (text){
				
				return text==null?
				"":
				trim.call(text);//此trim引用原生String.trim的功能，参见##148，相当于：text.trim();
				
			}
:
			
			// Otherwise use our own trimming functionality //当不存在原生String.trim的功能时，使用jQuery自己的实现功能
			function (text){
				
				return text==null?
				"":
				text.toString ().replace(trimLeft,"").replace(trimRight,"");//使用jQuery自己的实现功能
				
			},
			
			// results is for internal usage only //参数results仅在内部使用
			// 转换参数array（参数array是一个类似数组的对象）成为真正的JavaScript数组，并返回此数组。
			// 示例：var elems=document.getElementsByTagName("div");var arr=jQuery.makeArray(elems);//请先body内添加：<div>one</div><div>two</div><div>three</div><div>four</div>
			makeArray:function (array,results){
				
				var ret=results||[];//初始化数组
				
				if(array!=null){
					
					// The window, strings (and functions) also have 'length'
					// The extra typeof function check is to prevent crashes
					// in Safari 2 (See: #3039)
					// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues
					// #6930
					var type=jQuery.type(array);
					
					if(array.length==null||type==="string"||type==="function"||type==="regexp"||jQuery.isWindow(array)){
						
						push.call(ret,array);//相当于ret.push(array);把参数array添加到数组ret的尾部
						
					}else {
						
						jQuery.merge(ret,array);//将array合并入ret中
						
					}
					
				}

				
				return ret;				
				
			},
			
			// 检索并返回参数elem在数组array中的索引位置：若找到返回索引位置下标，否则，若没有返回-1。
			// 示例：var e=10,a=[0,5,10,15,20];alert(jQuery.inArray(e,a));
			inArray:function (elem,array){
				
				
				if(indexOf){
					
					return indexOf.call(array,elem);					
					
				}

				
				for(var i=0,length=array.length;i<length;i++){
					
					if(array[i]===elem){
						
						return i;						
						
					}
					
				}

				
				return -1;				
				
			},
			
			// 用于将second合并入first中，并返回合并后的新first
			// 示例：var f=[1,2,3,4,5],s=[10,20,30,40,50];alert(jQuery.merge(f,s));
			merge:function (first,second){//#s1127-e1156
				
				var i=first.length,
				j=0;				
				
				if(typeof second.length==="number"){
					
					for(var l=second.length;j<l;j++){
						
						first[i++]=second[j];						
						
					}
					
					
				}else {
					
					while(second[j]!==undefined){
						
						first[i++]=second[j++];						
						
					}
					
				}

				
				first.length=i;				
				
				return first;				
				
			},//#s1127-e1156
			
			// 用于查找满足过滤功能数组元素。原始数组不受影响。
			// 即：从数组参数elems中过滤符合callback回调函数要求的元素，inv参数用于标记到底是按callback回调为true的情况过滤，还是按为false的情况过滤。其中，inv参数是可选的，默认按为true的情况过滤。
			// 示例：var abc=[1,2,3,4,5,10,20,30,40,50];alert(jQuery.grep(abc,function(n,i){return i<5;}));//可对比alert(jQuery.grep(abc,function(n,i){return i<5;},true));的结果
			grep:function (elems,callback,inv){
				
				var ret=[],retVal;				
				inv=!!inv;				
				
				// Go through the array, only saving the items
				// that pass the validator function
				for(var i=0,length=elems.length;i<length;i++){
					
					retVal=!!callback(elems[i],i);					
					if(inv!==retVal){
						
						ret.push(elems[i]);						
						
					}
					
				}

				
				return ret;				
				
			},
			
			// arg is for internal usage only //参数arg仅供内部使用
			// 用于将数组或对象每个项目新阵列映射到一个新数组的函数
			// 即：将参数elems（一个数组或类似数组的对象）按callback回调的映射规则重新组织生成一个新数组，并返回此新数组。
			// 示例：var elems=['a','b','c','d'];var b=jQuery.map(elems, function(n, i){return (n.toUpperCase() + i);});alert(b);//返回b=['A0','B1','C2','D3'];
			map:function (elems,callback,arg){
				
				var value,key,ret=[],
				i=0,
				length=elems.length,
				// jquery objects are treated as arrays
				isArray=elems instanceof jQuery||length!==undefined&&typeof length==="number"&&((length>0&&elems[0]&&elems[length-1])||length===0||jQuery.isArray(elems));				
				
				// Go through the array, translating each of the items to their
				if(isArray){
					
					for(;i<length;i++){
						
						value=callback(elems[i],i,arg);						
						
						if(value!=null){
							
							ret[ret.length]=value;							
							
						}
						
					}

					
					// Go through every key on the object,
					
				}else {
					
					for(key in elems){
						
						value=callback(elems[key],key,arg);						
						
						if(value!=null){
							
							ret[ret.length]=value;							
							
						}
						
					}
					
				}

				
				// Flatten any nested arrays
				return ret.concat.apply([],ret);//相当于[].concat(ret);
				
			},
			
			// A global GUID counter for objects //用于标识object对象的全局GUID计数器
			guid:1,
			
			// Bind a function to a context, optionally partially applying any
			// arguments.
			// 接受一个函数，然后返回一个新函数，并且这个新函数始终保持了特定的上下文语境。
			proxy:function (fn,context){
				
				if(typeof context==="string"){
					
					var tmp=fn[context];					
					context=fn;					
					fn=tmp;					
					
				}

				
				// Quick check to determine if target is callable, in the spec
				// this throws a TypeError, but we will just return undefined.
				if(!jQuery.isFunction(fn)){
					
					return undefined;					
					
				}

				
				// Simulated bind
				var args=slice.call(arguments,2),//相当于arguments.slice(2);这里的slice()是数组(Array)原型的方法，格式：slice(start,[end])，该方法返回一个新数组，包含了源函数从start到 end所指定的元素
				proxy=function (){
					
					return fn.apply(context,args.concat(slice.call(arguments)));					
					
				};				
				
				// Set the guid of unique handler to the same of original handler, so it
				// can be removed
				proxy.guid=fn.guid=fn.guid||proxy.guid||jQuery.guid++;				
				
				return proxy;				
				
			},
			
			// Mutifunctional method to get and set values to a collection
			// The value/s can optionally be executed if it's a function
			/**
			 * 多功能的方法：用于获取和设置值集合的值，如果它是一个函数，可以有选择地执行
			 */
			access:function (elems,key,value,exec,fn,pass){
				
				var length=elems.length;				
				
				// Setting many attributes
				if(typeof key==="object"){
					
					for(var k in key){
						
						jQuery.access(elems,k,key[k],exec,fn,value);						
						
					}

					return elems;					
					
				}

				
				// Setting one attribute
				if(value!==undefined){
					
					// Optionally, function values get executed if exec is true
					exec=!pass&&exec&&jQuery.isFunction(value);					
					
					for(var i=0;i<length;i++){
						
						fn(elems[i],key,exec?value.call(elems[i],i,fn(elems[i],key)):value,pass);						
						
					}

					
					return elems;					
					
				}

				
				// Getting an attribute
				return length?fn(elems[0],key):undefined;				
				
			},
			
			// 用于返回客户端的当前时间距 1970 年 1 月 1 日之间的毫秒数。示例：alert(jQuery.now());
			now:function (){
				
				return (new Date()).getTime();				
				
			},
			
			// Use of jQuery.browser is frowned upon.
			// More details: http://docs.jquery.com/Utilities/jQuery.browser
			// 用于解析浏览器，返回浏览器类型和主版本号
			uaMatch:function (ua){
				
				ua=ua.toLowerCase();				
				
				var match=rwebkit.exec(ua)||
				ropera.exec(ua)||
				rmsie.exec(ua)||
				ua.indexOf("compatible")<0&&rmozilla.exec(ua)||
				[];
				
				return {
					browser:match[1]||"",version:match[2]||"0" //match[1]为浏览器类型，match[2]为主版本号
				};
				
			},
			
			//用于创建一个新的jQuery副本，不影响原有的jQuery对像。
			sub:function (){
				
				function jQuerySub(selector,context){
					
					return new jQuerySub.fn.init(selector,context);					
					
				}

				jQuery.extend(true,jQuerySub,this);				
				jQuerySub.superclass=this;				
				jQuerySub.fn=jQuerySub.prototype=this();				
				jQuerySub.fn.constructor =jQuerySub;				
				jQuerySub.sub=this.sub;				
				jQuerySub.fn.init=function init(selector,context){
					
					if(context&&context instanceof jQuery&&!(context instanceof jQuerySub)){
						
						context=jQuerySub(context);						
						
					}

					
					return jQuery.fn.init.call(this,selector,context,rootjQuerySub);					
					
				};				
				jQuerySub.fn.init.prototype=jQuerySub.fn;				
				var rootjQuerySub=jQuerySub(document);				
				return jQuerySub;				
				
			},
			
			// 浏览器信息，包含浏览器的类型和版本号等，这里现在只是“空壳”，后面会填充内容，参见下面的##1455和##1464的代码
			browser:{
				
			}
			
		});//#s586-e1365		
		
		// Populate the class2type map
		// 填充class2type的映射对
		jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "),function (i,name){
			
			class2type["[object "+name+"]"]=name.toLowerCase();	//##1451
			
		});
		
		//解析浏览器
		browserMatch=jQuery.uaMatch(userAgent);
		if(browserMatch.browser){//##1455
			
			jQuery.browser[browserMatch.browser]=true;
			jQuery.browser.version=browserMatch.version;	
			
		}

		
		// Deprecated, use jQuery.browser.webkit instead //已过时，请使用jQuery.browser.webkit代替
		if(jQuery.browser.webkit){//##1464
			
			jQuery.browser.safari=true;
			
		}

		
		// IE doesn't match non-breaking spaces with \s //由于在IE中不匹配非中断空格，需要对trimLeft和trimRight重新设置
		if(rnotwhite.test("\xA0")){
			
			trimLeft=/^[\s\xA0]+/;
			trimRight=/[\s\xA0]+$/;
			
		}

		
		// All jQuery objects should point back to these
		/**
		 * 在WEB页面加载时，以document为选择器初始化所有的jQuery对象
		 */
		rootjQuery=jQuery(document);//##1405		
		
		/**
		 * 参见：http://www.cnblogs.com/zhangziqiu/archive/2011/06/27/DOMReady.html和http://www.cnblogs.com/rubylouvre/archive/2009/08/26/1554204.html
		 */
		// Cleanup functions for the document ready method // 清除文档document的ready就绪时绑定的所有函数方法
		if(document.addEventListener){//对于Mozilla、Opera和webkit等浏览器
			
			DOMContentLoaded=function (){//##s1455
				
				document.removeEventListener("DOMContentLoaded",DOMContentLoaded,false);
				jQuery.ready();
				
			};			
			
			
		}else if(document.attachEvent){//IE浏览器
			
			DOMContentLoaded=function (){//##s1465
				
				// Make sure body exists, at least, in case IE gets a little overzealous
				// (ticket #5443).
				if(document.readyState==="complete"){
					
					document.detachEvent("onreadystatechange",DOMContentLoaded);					
					jQuery.ready();					
					
				}
				
			};			
			
		}

		
		// The DOM ready check for Internet Explorer //用于IE检测DOM readby是否完成
		function doScrollCheck(){
			
			if(jQuery.isReady){
				
				return ;				
				
			}

			
			try{
				
				// If IE is used, use the trick by Diego Perini
				// http://javascript.nwbox.com/IEContentLoaded/
				document.documentElement.doScroll("left");//如果执行这个操作时不再抛出异常,说明dom已经加载完毕了
				
			}catch(e){
				
				setTimeout(doScrollCheck,1);				
				return ;				
				
			}

			
			// and execute any waiting functions
			jQuery.ready();
			
		}

		
		return jQuery;//返回jQuery对象，用于实现“链式调用”
		
		
	})();	//#s31-e1375：jQuery框架的核心定义基本结束
	
	
	//1============================================================================================
	
	
	var // Promise methods
	promiseMethods="done fail isResolved isRejected promise then always pipe".split(" "),
	// Static reference to slice
	sliceDeferred=[].slice;	
	
	
	//1============================================================================================
	
	
	jQuery.extend({//#s1390-e1687
		
		// Create a simple deferred (one callbacks list)
		// 创建一个简单的缓存（一个回调列表）
		_Deferred:function (){//#s1495-e1614
			
			var // callbacks list
			callbacks=[],
			// stored [ context , args ]
			fired,
			// to avoid firing when already doing so
			firing,
			// flag to know if the deferred has been cancelled
			cancelled,
			// the deferred itself
			deferred={
				
				
				// done( f1, f2, ...)
				done:function (){
					
					if(!cancelled){
						
						var args=arguments,
						i,
						length,
						elem,
						type,
						_fired;						
						if(fired){
							
							_fired=fired;							
							fired=0;							
							
						}

						for(i=0,length=args.length;i<length;i++){
							
							elem=args[i];							
							type=jQuery.type(elem);							
							if(type==="array"){
								
								deferred.done.apply(deferred,elem);								
								
							}else if(type==="function"){
								
								callbacks.push(elem);								
								
							}
							
						}

						if(_fired){
							
							deferred.resolveWith(_fired[0],_fired[1]);							
							
						}
						
					}

					return this;					
					
				},
				
				// resolve with given context and args
				resolveWith:function (context,args){
					
					if(!cancelled&&!fired&&!firing){
						
						// make sure args are available (#8421)
						args=args||[];						
						firing=1;						
						try{
							
							while(callbacks[0]){
								
								callbacks.shift().apply(context,args);								
								
							}
							
						}

						finally{
							
							fired=[context,args];							
							firing=0;							
							
						}
						
					}

					return this;					
					
				},
				
				// resolve with this as context and given arguments
				resolve:function (){
					
					deferred.resolveWith(this,arguments);					
					return this;					
					
				},
				
				// Has this deferred been resolved? //返回是否还有缓存没有解决（执行）
				isResolved:function (){
					
					return !!(firing||fired);			
					
				},
				
				// Cancel //取消执行缓存
				cancel:function (){
					
					cancelled=1;					
					callbacks=[];					
					return this;					
					
				}
				
			};			
			
			return deferred;			
			
		},//#s1495-e1614
		
		// Full fledged deferred (two callbacks list)
		Deferred:function (func){
			
			var deferred=jQuery._Deferred(),
			failDeferred=jQuery._Deferred(),
			promise;			
			// Add errorDeferred methods, then and promise
			jQuery.extend(deferred,{
				
				then:function (doneCallbacks,failCallbacks){
					
					deferred.done(doneCallbacks).fail(failCallbacks);					
					return this;					
					
				},
				always:function (){
					
					return deferred.done.apply(deferred,arguments).fail.apply(this,arguments);					
					
				},
				fail:failDeferred.done,
				rejectWith:failDeferred.resolveWith,
				reject:failDeferred.resolve,
				isRejected:failDeferred.isResolved,
				pipe:function (fnDone,fnFail){
					
					return jQuery.Deferred(function (newDefer){
						
						jQuery.each({
							
							done:[fnDone,"resolve"],
							fail:[fnFail,"reject"]
							
						},function (handler,data){
							
							var fn=data[0],
							action=data[1],
							returned;							
							if(jQuery.isFunction(fn)){
								
								deferred[handler](function (){
									
									returned=fn.apply(this,arguments);									
									if(returned&&jQuery.isFunction(returned.promise)){
										
										returned.promise().then(newDefer.resolve,newDefer.reject);										
										
									}else {
										
										newDefer[action](returned);										
										
									}
									
								});								
								
							}else {
								
								deferred[handler](newDefer[action]);								
								
							}
							
						});						
						
					}).promise();					
					
				},
				// Get a promise for this deferred
				// If obj is provided, the promise aspect is added to the object
				promise:function (obj){
					
					if(obj==null){
						
						if(promise){
							
							return promise;							
							
						}

						promise=obj={
							
						};						
						
					}

					var i=promiseMethods.length;					
					while(i--){
						
						obj[promiseMethods[i]]=deferred[promiseMethods[i]];						
						
					}

					return obj;					
					
				}
				
			});			
			// Make sure only one callback list will be used
			deferred.done(failDeferred.cancel).fail(deferred.cancel);			
			// Unexpose cancel
			delete deferred.cancel;			
			// Call given func if any
			if(func){
				
				func.call(deferred,deferred);				
				
			}

			return deferred;			
			
		},
		
		// Deferred helper
		when:function (firstParam){
			
			var args=arguments,
			i=0,
			length=args.length,
			count=length,
			deferred=length<=1&&firstParam&&jQuery.isFunction(firstParam.promise)?
			firstParam:
			jQuery.Deferred();			
			function resolveFunc(i){
				
				return function (value){
					
					args[i]=arguments.length>1?sliceDeferred.call(arguments,0):value;					
					if(!(--count)){
						
						// Strange bug in FF4:
						// Values changed onto the arguments object sometimes end up
						// as undefined values
						// outside the $.when method. Cloning the object into a
						// fresh array solves the issue
						deferred.resolveWith(deferred,sliceDeferred.call(args,0));						
						
					}
					
				};				
				
			}

			if(length>1){
				
				for(;i<length;i++){
					
					if(args[i]&&jQuery.isFunction(args[i].promise)){
						
						args[i].promise().then(resolveFunc(i),deferred.reject);						
						
					}else {
						
						--count;						
						
					}
					
				}

				if(!count){
					
					deferred.resolveWith(deferred,args);					
					
				}
				
			}else if(deferred!==firstParam){
				
				deferred.resolveWith(deferred,length?[firstParam]:[]);				
				
			}

			return deferred.promise();			
			
		}
		
	});	//#s1390-e1687
	
	
	//1============================================================================================
	
	/**
	 * 包含一组有用的属性，它们代表了不同的浏览器功能或缺陷的存在的集合。
	 * 这是一个很好的做法，执行功能检测
	 */
	jQuery.support=(function (){//#s1693-e1992
		
		
		var div=document.createElement("div"),
		documentElement=document.documentElement,
		all,
		a,
		select,
		opt,
		input,
		marginDiv,
		support,
		fragment,
		body,
		testElementParent,
		testElement,
		testElementStyle,
		tds,
		events,
		eventName,
		i,
		isSupported;		
		
		// Preliminary tests //初步测试的代码，下面将用于测试执行功能
		div.setAttribute("className","t");		
		div.innerHTML="   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>";		
		
		all=div.getElementsByTagName("*");		
		a=div.getElementsByTagName("a")[0];		
		
		// Can't get basic test support
		if(!all||!all.length||!a){
			
			return {
				
			};			
			
		}

		
		// First batch of supports tests
		select=document.createElement("select");		
		opt=select.appendChild(document.createElement("option"));		
		input=div.getElementsByTagName("input")[0];		

		/**
		 * 包含一组有用的属性，它们代表了不同的浏览器功能或缺陷的存在的集合。
		 * 这是一个很好的做法，执行功能检测
		 */
		support={//#s1925-e1981
			
			// IE strips leading whitespace when .innerHTML is used 
			//用于判断浏览器插入的内容完全按照所提供的.innerHTML代码一致，等于true时，也会插入.innerHTML的前面空白字符，等于false时，则相反（目前在IE 6-8中会返回false） 
			leadingWhitespace:(div.firstChild.nodeType===3),
			
			// Make sure that tbody elements aren't automatically inserted
			// IE will insert them into empty tables
			tbody:!div.getElementsByTagName("tbody").length,
			
			// Make sure that link elements get serialized correctly by innerHTML
			// This requires a wrapper element in IE
			htmlSerialize:!!div.getElementsByTagName("link").length,
			
			// Get the style information from getAttribute
			// (IE uses .cssText instead)
			style:/top/.test(a.getAttribute("style")),
			
			// Make sure that URLs aren't manipulated
			// (IE normalizes it by default)
			hrefNormalized:(a.getAttribute("href")==="/a"),
			
			// Make sure that element opacity exists
			// (IE uses filter instead)
			// Use a regex to work around a WebKit issue. See #5145
			opacity:/^0.55$/.test(a.style.opacity),
			
			// Verify style float existence
			// (IE uses styleFloat instead of cssFloat)
			cssFloat:!!a.style.cssFloat,
			
			// Make sure that if no value is specified for a checkbox
			// that it defaults to "on".
			// (WebKit defaults to "" instead)
			checkOn:(input.value==="on"),
			
			// Make sure that a selected-by-default option has a working selected
			// property.
			// (WebKit defaults to false instead of true, IE too, if it's in an
			// optgroup)
			optSelected:opt.selected,
			
			// Test setAttribute on camelCase class. If it works, we need attrFixes
			// when doing get/setAttribute (ie6/7)
			getSetAttribute:div.className!=="t",
			
			// Will be defined later
			submitBubbles:true,
			changeBubbles:true,
			focusinBubbles:false,
			deleteExpando:true,
			noCloneEvent:true,
			inlineBlockNeedsLayout:false,
			shrinkWrapBlocks:false,
			reliableMarginRight:true
			
		};//#s1925-e1981
		
		// Make sure checked status is properly cloned
		input.checked=true;		
		support.noCloneChecked=input.cloneNode(true).checked;		
		
		// Make sure that the options inside disabled selects aren't marked as
		// disabled
		// (WebKit marks them as disabled)
		select.disabled=true;		
		support.optDisabled=!opt.disabled;		
		
		// Test to see if it's possible to delete an expando from an element
		// Fails in Internet Explorer
		try{
			
			delete div.test;			
			
		}catch(e){
			
			support.deleteExpando=false;			
			
		}

		
		if(!div.addEventListener&&div.attachEvent&&div.fireEvent){
			
			div.attachEvent("onclick",function (){
				
				// Cloning a node shouldn't copy over any
				// bound event handlers (IE does this)
				support.noCloneEvent=false;				
				
			});			
			div.cloneNode(true).fireEvent("onclick");			
			
		}

		
		// Check if a radio maintains it's value
		// after being appended to the DOM
		input=document.createElement("input");		
		input.value="t";		
		input.setAttribute("type","radio");		
		support.radioValue=input.value==="t";		
		
		input.setAttribute("checked","checked");		
		div.appendChild(input);		
		fragment=document.createDocumentFragment();		
		fragment.appendChild(div.firstChild);		
		
		// WebKit doesn't clone checked state correctly in fragments
		support.checkClone=fragment.cloneNode(true).cloneNode(true).lastChild.checked;		
		
		div.innerHTML="";		
		
		// Figure out if the W3C box model works as expected
		div.style.width=div.style.paddingLeft="1px";		
		
		body=document.getElementsByTagName("body")[0];		
		// We use our own, invisible, body unless the body is already present
		// in which case we use a div (#9239)
		testElement=document.createElement(body?"div":"body");		
		testElementStyle={
			
			visibility:"hidden",
			width:0,
			height:0,
			border:0,
			margin:0
			
		};		
		if(body){
			
			jQuery.extend(testElementStyle,{
				
				position:"absolute",
				left:-1000,
				top:-1000
				
			});			
			
		}

		for(i in testElementStyle){
			
			testElement.style[i]=testElementStyle[i];			
			
		}

		testElement.appendChild(div);		
		testElementParent=body||documentElement;		
		testElementParent.insertBefore(testElement,testElementParent.firstChild);		
		
		// Check if a disconnected checkbox will retain its checked
		// value of true after appended to the DOM (IE6/7)
		support.appendChecked=input.checked;		
		
		support.boxModel=div.offsetWidth===2;		
		
		if("zoom" in div.style){
			
			// Check if natively block-level elements act like inline-block
			// elements when setting their display to 'inline' and giving
			// them layout
			// (IE < 8 does this)
			div.style.display="inline";			
			div.style.zoom=1;			
			support.inlineBlockNeedsLayout=(div.offsetWidth===2);			
			
			// Check if elements with layout shrink-wrap their children
			// (IE 6 does this)
			div.style.display="";			
			div.innerHTML="<div style='width:4px;'></div>";			
			support.shrinkWrapBlocks=(div.offsetWidth!==2);			
			
		}

		
		div.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";		
		tds=div.getElementsByTagName("td");		
		
		// Check if table cells still have offsetWidth/Height when they are set
		// to display:none and there are still other visible table cells in a
		// table row; if so, offsetWidth/Height are not reliable for use when
		// determining if an element has been hidden directly using
		// display:none (it is still safe to use offsets if a parent element is
		// hidden; don safety goggles and see bug #4512 for more information).
		// (only IE 8 fails this test)
		isSupported=(tds[0].offsetHeight===0);		
		
		tds[0].style.display="";		
		tds[1].style.display="none";		
		
		// Check if empty table cells still have offsetWidth/Height
		// (IE < 8 fail this test)
		support.reliableHiddenOffsets=isSupported&&(tds[0].offsetHeight===0);		
		div.innerHTML="";		
		
		// Check if div with explicit width and no margin-right incorrectly
		// gets computed margin-right based on width of container. For more
		// info see bug #3333
		// Fails in WebKit before Feb 2011 nightlies
		// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
		if(document.defaultView&&document.defaultView.getComputedStyle){
			
			marginDiv=document.createElement("div");			
			marginDiv.style.width="0";			
			marginDiv.style.marginRight="0";			
			div.appendChild(marginDiv);			
			support.reliableMarginRight=
			(parseInt((document.defaultView.getComputedStyle(marginDiv,null)||{
				marginRight:0
			}).marginRight,10)||0)===0;			
			
		}

		
		// Remove the body element we added
		testElement.innerHTML="";		
		testElementParent.removeChild(testElement);		
		
		// Technique from Juriy Zaytsev
		// http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
		// We only care about the case where non-standard event systems
		// are used, namely in IE. Short-circuiting here helps us to
		// avoid an eval call (in setAttribute) which can cause CSP
		// to go haywire. See: https://developer.mozilla.org/en/Security/CSP
		if(div.attachEvent){
			
			for(i in {
				
				submit:1,
				change:1,
				focusin:1
				
			}){
				
				eventName="on"+i;				
				isSupported=(eventName in div);				
				if(!isSupported){
					
					div.setAttribute(eventName,"return;");					
					isSupported=(typeof div[eventName]==="function");					
					
				}

				support[i+"Bubbles"]=isSupported;				
				
			}
			
		}

		
		// Null connected elements to avoid leaks in IE
		testElement=fragment=select=opt=body=marginDiv=div=input=null;		
		
		return support;		
		
	})();	//#s1693-e1992
	
	
	//1============================================================================================
	
	
	// Keep track of boxModel
	jQuery.boxModel=jQuery.support.boxModel;
	
	
	var rbrace=/^(?:\{.*\}|\[.*\])$/,//匹配所有以{开始和}结尾或以[开始和]结尾的字符串。示例：var a="{}",b="[]",c="{abc}",d="[cba]"等
	rmultiDash=/([a-z])([A-Z])/g;//匹配一个小写字母后跟一个大写字母，全局匹配。示例：var a="aB",b="bC"等
	
	
	//1============================================================================================
	
	
	jQuery.extend({//#s2009-e2334
		
		//声明缓存的变量
		cache:{
			
		},
		
		// Please use with caution
		uuid:0,
		
		// Unique for each copy of jQuery on the page
		// Non-digits removed to match rinlinejQuery
		expando:"jQuery"+(jQuery.fn.jquery+Math.random()).replace(/\D/g,""),
		
		// The following elements throw uncatchable exceptions if you
		// attempt to add expando properties to them.
		noData:{
			
			"embed":true,
			// Ban all objects except for Flash (which handle expandos)
			"object":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
			"applet":true
			
		},
		
		//用于判断参数elem中是否有数据，这些数据是使用下面#s2230-e2367的jQuery.data()方法设置的。如果没有数据，该方法返回false，否则返回true。
		//示例：var $p=jQuery("p"),p=$p[0]; $p.append(jQuery.hasData(p)+"");/*false*/ jQuery.data(p,"testing",123); jQuery.removeData(p,"testing"); $p.append(jQuery.hasData(p)+"");/*false*/
		hasData:function (elem){
			
			elem=elem.nodeType?jQuery.cache[elem[jQuery.expando]]:elem[jQuery.expando];			
			
			return !!elem&&!isEmptyDataObject(elem);			
			
		},
		
		//以name为标识符附加数据data到参数elem上。其中，elem为主体，name为data的key，data为value，pvt为内部参数（仅在内部使用）。
		//示例：(1)设置：jQuery.data(document.body, 'mykey', 123456);(2)访问：jQuery.data(document.body, 'mykey');
		data:function (elem,name,data,pvt/* Internal Use Only */){//#s2230-e2367
			
			if(!jQuery.acceptData(elem)){//判断参数elem是否可以接收扩展数据。见#s2504-e2521
				
				return ;				
				
			}

			
			var internalKey=jQuery.expando,getByName=typeof name==="string",thisCache,
			
			// We have to handle DOM nodes and JS objects differently because
			// IE6-7
			// can't GC object references properly across the DOM-JS boundary
			isNode=elem.nodeType,
			
			// Only DOM nodes need the global jQuery cache; JS object data is
			// attached directly to the object so GC can occur automatically
			cache=isNode?jQuery.cache:elem,
			
			// Only defining an ID for JS objects if its cache already exists
			// allows
			// the code to shortcut on the same path as a DOM node with no cache
			id=isNode?elem[jQuery.expando]:elem[jQuery.expando]&&jQuery.expando;			
			
			// Avoid doing any more work than we need to when trying to get data on
			// an
			// object that has no data at all
			if((!id||(pvt&&id&&!cache[id][internalKey]))&&getByName&&data===undefined){
				
				return ;				
				
			}

			
			if(!id){
				
				// Only DOM nodes need a new unique ID for each element since their
				// data
				// ends up in the global cache
				if(isNode){
					
					elem[jQuery.expando]=id=++jQuery.uuid;					
					
				}else {
					
					id=jQuery.expando;					
					
				}
				
			}

			
			if(!cache[id]){
				
				cache[id]={
					
				};				
				
				// TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery
				// metadata on plain JS objects when the object is serialized using
				// JSON.stringify
				if(!isNode){
					
					cache[id].toJSON=jQuery.noop;					
					
				}
				
			}

			
			// An object can be passed to jQuery.data instead of a key/value pair;
			// this gets
			// shallow copied over onto the existing cache
			if(typeof name==="object"||typeof name==="function"){
				
				if(pvt){
					
					cache[id][internalKey]=jQuery.extend(cache[id][internalKey],name);					
					
				}else {
					
					cache[id]=jQuery.extend(cache[id],name);					
					
				}
				
			}

			
			thisCache=cache[id];			
			
			// Internal jQuery data is stored in a separate object inside the
			// object's data
			// cache in order to avoid key collisions between internal data and
			// user-defined
			// data
			if(pvt){
				
				if(!thisCache[internalKey]){
					
					thisCache[internalKey]={
						
					};					
					
				}

				
				thisCache=thisCache[internalKey];				
				
			}

			
			if(data!==undefined){
				
				thisCache[jQuery.camelCase(name)]=data;				
				
			}

			
			// TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users
			// should
			// not attempt to inspect the internal events object using jQuery.data,
			// as this
			// internal data object is undocumented and subject to change.
			if(name==="events"&&!thisCache[name]){
				
				return thisCache[internalKey]&&thisCache[internalKey].events;				
				
			}

			
			return getByName?
			// Check for both converted-to-camel and non-converted data property
			// names
			thisCache[jQuery.camelCase(name)]||thisCache[name]:
			thisCache;			
			
		},//#s2230-e2367
		
		//在元素上移除绑定的数据，即从elem上移除标识名为参数name的数据。此方法的作用与#s2230-e2367的jQuery.data方法作用刚好相反
		//示例：(1)附加数据：jQuery.data(document.body, 'mykey', 123456);(2)移除数据：jQuery.removeData(document.body, 'mykey');
		removeData:function (elem,name,pvt/* Internal Use Only */){//#s2375-e2500
			
			if(!jQuery.acceptData(elem)){
				
				return ;				
				
			}

			
			var internalKey=jQuery.expando,isNode=elem.nodeType,
			
			// See jQuery.data for more information
			cache=isNode?jQuery.cache:elem,
			
			// See jQuery.data for more information
			id=isNode?elem[jQuery.expando]:jQuery.expando;			
			
			// If there is already no cache entry for this object, there is no
			// purpose in continuing
			if(!cache[id]){
				
				return ;				
				
			}

			
			if(name){
				
				var thisCache=pvt?cache[id][internalKey]:cache[id];				
				
				if(thisCache){
					
					delete thisCache[name];					
					
					// If there is no data left in the cache, we want to continue
					// and let the cache object itself get destroyed
					if(!isEmptyDataObject(thisCache)){
						
						return ;						
						
					}
					
				}
				
			}

			
			// See jQuery.data for more information
			if(pvt){
				
				delete cache[id][internalKey];				
				
				// Don't destroy the parent cache unless the internal data object
				// had been the only thing left in it
				if(!isEmptyDataObject(cache[id])){
					
					return ;					
					
				}
				
			}

			
			var internalCache=cache[id][internalKey];			
			
			// Browsers that fail expando deletion also refuse to delete expandos on
			// the window, but it will allow it on all other JS objects; other
			// browsers
			// don't care
			if(jQuery.support.deleteExpando||cache!=window){
				
				delete cache[id];				
				
			}else {
				
				cache[id]=null;				
				
			}

			
			// We destroyed the entire user cache at once because it's faster than
			// iterating through each key, but we need to continue to persist
			// internal
			// data if it existed
			if(internalCache){
				
				cache[id]={
					
				};				
				// TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery
				// metadata on plain JS objects when the object is serialized using
				// JSON.stringify
				if(!isNode){
					
					cache[id].toJSON=jQuery.noop;					
					
				}

				
				cache[id][internalKey]=internalCache;				
				
				// Otherwise, we need to eliminate the expando on the node to avoid
				// false lookups in the cache for entries that no longer exist
				
			}else if(isNode){
				
				// IE does not allow us to delete expando properties from nodes,
				// nor does it have a removeAttribute function on Document nodes;
				// we must handle all of these cases
				if(jQuery.support.deleteExpando){
					
					delete elem[jQuery.expando];					
					
				}else if(elem.removeAttribute){
					
					elem.removeAttribute(jQuery.expando);					
					
				}else {
					
					elem[jQuery.expando]=null;					
					
				}
				
			}
			
		},//#s2375-e2500
		
		// For internal use only. //此方法仅在内部使用，其实是调用#s2230-e2367的jQuery.data方法，因此作用相同
		_data:function (elem,name,data){
			
			return jQuery.data(elem,name,data,true);			
			
		},
		
		// A method for determining if a DOM node can handle the data expando
		// 用于判断是否可以接收（扩充、增加）参数elem变量，即判断是否可以为参数elem附加或绑定数据。返回true为可以接收，否则不能接收。
		acceptData:function (elem){//#s2504-e2521
			
			if(elem.nodeName){
				
				var match=jQuery.noData[elem.nodeName.toLowerCase()];				
				
				if(match){
					
					return !(match===true||elem.getAttribute("classid")!==match);
					
				}
				
			}

			
			return true;			
			
		}//#s2504-e2521
		
	});	//#s2009-e2334
	
	
	//1============================================================================================
	

	/**
	 * 重要：jQuery的插件实现的第二种方式（原型扩展方式），客户端手动增加其他插件时，可参考这里的实现格式。
	 * 格式：
	 * 		（1）定义格式：jQuery.fn.extend({插件名1:插件实现1, 插件名2:插件实现2...});
	 * 		（2）调用格式：jQuery("...").插件名(args)，或者$("...").插件名(args)
	 * 示例：
	 * 		（1）定义示例：jQuery.fn.extend({min:function(a,b){return a<b?a:b;},max:function(a,b){return a>=b?a:b;}});
	 * 		（2）调用示例：上面定义插件示例分别为返回两者中的小者和大者。alert($("body").min(3,5));alert($("body").max(3,5));
	 */
	jQuery.fn.extend({//#s2340-e2436
		
		//.data()方法允许我们在DOM元素上附加任意类型的数据,避免了循环引用的内存泄漏风险。
		//其中，key为存储的数据名。value为新数据值，它可以是任意的Javascript数据类型，包括Array 或者 Object。
		//示例：(1)设置：$('body').data('foo', 52);$('body').data('bar', { myType: 'test', count: 40 });
		//(2)访问：$('body').data('foo');/*52*/ $('body').data(); //{foo: 52, bar: { myType: 'test', count: 40 }}
		data:function (key,value){
			
			var data=null;			
			
			if(typeof key==="undefined"){
				
				if(this.length){
					
					data=jQuery.data(this[0]);					
					
					if(this[0].nodeType===1){//nodeType等于1：元素element节点
						
						var attr=this[0].attributes,name;						
						for(var i=0,l=attr.length;i<l;i++){
							
							name=attr[i].name;							
							
							if(name.indexOf("data-")===0){//自jQuery 1.4.3起， HTML元素的"data-属性"将自动被引用到jQuery的数据对象中。示例：<div data-role="page" data-hidden="true" data-options='{"name":"John"}'></div>
								
								name=jQuery.camelCase(name.substring(5));								
								
								dataAttr(this[0],name,data[name]);//见#s2442-e2483的	dataAttr方法
								
							}
							
						}
						
					}
					
				}

				
				return data;				
				
				
			}else if(typeof key==="object"){
				
				return this.each(function (){
					
					jQuery.data(this,key);					
					
				});				
				
			}

			
			var parts=key.split(".");
			parts[1]=parts[1]?"."+parts[1]:"";
			
			if(value===undefined){
				
				data=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);				
				
				// Try to fetch any internally stored data first
				if(data===undefined&&this.length){
					
					data=jQuery.data(this[0],key);					
					data=dataAttr(this[0],key,data);					
					
				}

				
				return data===undefined&&parts[1]?
				this.data(parts[0]):
				data;				
				
				
			}else {
				
				return this.each(function (){
					
					var $this=jQuery(this),
					args=[parts[0],value];					
					
					$this.triggerHandler("setData"+parts[1]+"!",args);					
					jQuery.data(this,key,value);					
					$this.triggerHandler("changeData"+parts[1]+"!",args);					
					
				});				
				
			}
			
		},
		
		//.removeData()方法允许我们移除用.data()绑定的值。当带name参数调用的时候，.removeData()将删除那个特有的值，当不带任何参数的时候，所有的值将被移除。
		//示例：(1)附加数据：$("div").data("test1", "VALUE-1");(2)移除数据：$("div").removeData("test1");
		removeData:function (key){
			
			return this.each(function (){
				
				jQuery.removeData(this,key);				
				
			});			
			
		}
		
	});	//#s2340-e2436
	
	
	//1============================================================================================
	
	
	function dataAttr(elem,key,data){//#s2442-e2483
		
		// If nothing was found internally, try to fetch any
		// data from the HTML5 data-* attribute
		// 试图从HTML5的"data-属性"中获取数据信息
		if(data===undefined&&elem.nodeType===1){
			
			var name="data-"+key.replace(rmultiDash,"$1-$2").toLowerCase();			
			
			data=elem.getAttribute(name);			
			
			if(typeof data==="string"){
				
				try{
					
					data=data==="true"?true:
					data==="false"?false:
					data==="null"?null:
					!jQuery.isNaN(data)?parseFloat(data):
					rbrace.test(data)?jQuery.parseJSON(data):
					data;					
					
				}catch(e){
					
				}

				
				// Make sure we set the data so it isn't changed later
				jQuery.data(elem,key,data);				
				
				
			}else {
				
				data=undefined;				
				
			}
			
		}

		
		return data;		
		
	}//#s2442-e2483
	
	
	//1============================================================================================

	
	// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON
	// property to be considered empty objects; this property always exists in
	// order to make sure JSON.stringify does not expose internal metadata
	// 此方法判断obj是否有toJSON属性，如果有返回true，否则返回false
	function isEmptyDataObject(obj){//#s2492-e2507
		
		for(var name in obj){
			
			if(name!=="toJSON"){
				
				return false;				
				
			}
			
		}
		
		
		return true;		
		
	}//#s2492-e2507
	
	
	//1============================================================================================
	
	
	function handleQueueMarkDefer(elem,type,src){//#s2513-e2539
		
		var deferDataKey=type+"defer",
		queueDataKey=type+"queue",
		markDataKey=type+"mark",
		defer=jQuery.data(elem,deferDataKey,undefined,true);		
		if(defer&&
		(src==="queue"||!jQuery.data(elem,queueDataKey,undefined,true))&&
		(src==="mark"||!jQuery.data(elem,markDataKey,undefined,true))){
			
			// Give room for hard-coded callbacks to fire first
			// and eventually mark/queue something else on the element
			setTimeout(function (){
				
				if(!jQuery.data(elem,queueDataKey,undefined,true)&&
				!jQuery.data(elem,markDataKey,undefined,true)){
					
					jQuery.removeData(elem,deferDataKey,true);					
					defer.resolve();					
					
				}
				
			},0);			
			
		}
		
	}//#s2513-e2539
	
	
	//1============================================================================================

	
	jQuery.extend({//#s2545-e2661
		
		
		_mark:function (elem,type){
			
			if(elem){
				
				type=(type||"fx")+"mark";				
				jQuery.data(elem,type,(jQuery.data(elem,type,undefined,true)||0)+1,true);				
				
			}
			
		},
		
		_unmark:function (force,elem,type){
			
			if(force!==true){
				
				type=elem;				
				elem=force;				
				force=false;				
				
			}

			if(elem){
				
				type=type||"fx";				
				var key=type+"mark",
				count=force?0:((jQuery.data(elem,key,undefined,true)||1)-1);				
				if(count){
					
					jQuery.data(elem,key,count,true);					
					
				}else {
					
					jQuery.removeData(elem,key,true);					
					handleQueueMarkDefer(elem,type,"mark");					
					
				}
				
			}
			
		},
		
		//动画队列
		queue:function (elem,type,data){
			
			if(elem){
				
				type=(type||"fx")+"queue";				
				var q=jQuery.data(elem,type,undefined,true);				
				// Speed up dequeue by getting out quickly if this is just a lookup
				if(data){
					
					if(!q||jQuery.isArray(data)){
						
						q=jQuery.data(elem,type,jQuery.makeArray(data),true);						
						
					}else {
						
						q.push(data);						
						
					}
					
				}

				return q||[];				
				
			}
			
		},
		
		//用于从动画队列中移除一个队列函数
		dequeue:function (elem,type){
			
			type=type||"fx";			
			
			var queue=jQuery.queue(elem,type),
			fn=queue.shift(),
			defer;			
			
			// If the fx queue is dequeued, always remove the progress sentinel
			if(fn==="inprogress"){
				
				fn=queue.shift();				
				
			}

			
			if(fn){
				
				// Add a progress sentinel to prevent the fx queue from being
				// automatically dequeued
				if(type==="fx"){
					
					queue.unshift("inprogress");					
					
				}

				
				fn.call(elem,function (){
					
					jQuery.dequeue(elem,type);					
					
				});				
				
			}

			
			if(!queue.length){
				
				jQuery.removeData(elem,type+"queue",true);				
				handleQueueMarkDefer(elem,type,"queue");				
				
			}
			
		}
		
	});	//#s2545-e2661
	
	
	//1============================================================================================
	
	
	jQuery.fn.extend({//#s2667-e2779
		
		//动画队列
		queue:function (type,data){
			
			if(typeof type!=="string"){
				
				data=type;				
				type="fx";				
				
			}

			
			if(data===undefined){
				
				return jQuery.queue(this[0],type);				
				
			}

			return this.each(function (){
				
				var queue=jQuery.queue(this,type,data);				
				
				if(type==="fx"&&queue[0]!=="inprogress"){
					
					jQuery.dequeue(this,type);					
					
				}
				
			});			
			
		},
		
		//用于从动画队列中移除一个队列函数
		dequeue:function (type){
			
			return this.each(function (){
				
				jQuery.dequeue(this,type);				
				
			});			
			
		},
		// Based off of the plugin by Clint Helfers, with permission.
		// http://blindsignals.com/index.php/2009/07/jquery-delay/
		// .delay()方法允许我们将队列中的函数延时执行。它既可以推迟动画队列中函数的执行，也可以用于自定义队列，延时时间是以毫秒为单位的
		// 示例：$('#foo').slideUp(300).delay(800).fadeIn(400);//在 <div id="foo"> 的 .slideUp() 和 .fadeIn() 动画之间设置800毫秒的延时。即当这句语句执行的时候，这个foo元素会以300毫秒的卷起动画，然后在400毫秒淡入动画前暂停800毫秒。
		delay:function (time,type){
			
			time=jQuery.fx?jQuery.fx.speeds[time]||time:time;			
			type=type||"fx";			
			
			return this.queue(type,function (){
				
				var elem=this;				
				setTimeout(function (){
					
					jQuery.dequeue(elem,type);					
					
				},time);				
				
			});			
			
		},
		
		//用于从动画列队中移除所有未执行的函数项。
		clearQueue:function (type){
			
			return this.queue(type||"fx",[]);			
			
		},
		
		// Get a promise resolved when queues of a certain type
		// are emptied (fx is the type by default)
		promise:function (type,object){
			
			if(typeof type!=="string"){
				
				object=type;				
				type=undefined;				
				
			}

			type=type||"fx";			
			var defer=jQuery.Deferred(),
			elements=this,
			i=elements.length,
			count=1,
			deferDataKey=type+"defer",
			queueDataKey=type+"queue",
			markDataKey=type+"mark",
			tmp;			
			function resolve(){
				
				if(!(--count)){
					
					defer.resolveWith(elements,[elements]);					
					
				}
				
			}
			while(i--){
				
				if((tmp=jQuery.data(elements[i],deferDataKey,undefined,true)||
				(jQuery.data(elements[i],queueDataKey,undefined,true)||
				jQuery.data(elements[i],markDataKey,undefined,true))&&
				jQuery.data(elements[i],deferDataKey,jQuery._Deferred(),true))){
					
					count++;					
					tmp.done(resolve);					
					
				}
				
			}

			resolve();			
			return defer.promise();			
			
		}
		
	});	//#s2667-e2779
	
	
	//1============================================================================================
	
	
	var rclass=/[\n\t\r]/g,
	rspace=/\s+/,
	rreturn=/\r/g,
	rtype=/^(?:button|input)$/i,
	rfocusable=/^(?:button|input|object|select|textarea)$/i,
	rclickable=/^a(?:rea)?$/i,
	rboolean=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
	rinvalidChar=/\:|^on/,
	formHook,boolHook;	
	
	
	//1============================================================================================
	

	/**
	 * 扩展jQuery原型
	 * @param {Object} name
	 * @param {Object} value
	 */
	jQuery.fn.extend({//#s2779-e3121
		
		/**
		 * 读取或设置name属性的属性值：
		 * 1、只有一个参数时，获取name属性的属性值
		 * 2、有两个参数时，设置name属性的属性值为value的值
		 */
		//示例：(1)获取属性：$('#greatphoto').attr('alt');(2)设置属性：$('#greatphoto').attr('alt', '123456');//请先在body中添加<img id="greatphoto" alt="abcdef" />
		attr:function (name,value){//#s2898-e2902
			
			return jQuery.access(this,name,value,true,jQuery.attr);			
			
		},
		
		//用于移除属性：移除的属性由参数name指定，与上面#s2898-e2902的attr()函数的作用刚好相反
		//示例：$('#abcd').removeAttr("disabled");//请先在body中添加<input type="text" id="abcd" disabled="disabled" value="can't edit this" />
		removeAttr:function (name){
			
			return this.each(function (){
				
				jQuery.removeAttr(this,name);				
				
			});			
			
		},
		
		//用于获取或设置在匹配的元素集中的第一个元素的属性值，非常类似上面#s2898-e2902的attr()函数，但有一些小区别
		//示例：(1)alert($('#abcd').prop('checked'));//弹出true (2)alert($('#abcd').attr('checked'));//弹出checked (3)请先在body中添加<input id="abcd" type="checkbox" checked="checked">
		prop:function (name,value){//#s3046-e3050
			
			return jQuery.access(this,name,value,true,jQuery.prop);			
			
		},
		
		//作用与上面#s3046-e3050的prop函数的作用刚好相反，用来删除由.prop()方法设置的属性集。
		removeProp:function (name){
			
			name=jQuery.propFix[name]||name;			
			return this.each(function (){
				
				// try/catch handles cases where IE balks (such as removing a
				// property on window)
				try{
					
					this[name]=undefined;					
					delete this[name];					
					
				}catch(e){
					
				}
				
			});			
			
		},
		
		/**
		 * 为匹配的元素添加指定的样式名
		 */
		addClass:function (value){//#s3076-e3134
			
			var classNames,i,l,elem,
			setClass,c,cl;			
			
			if(jQuery.isFunction(value)){
				
				return this.each(function (j){
					
					jQuery(this).addClass(value.call(this,j,this.className));					
					
				});				
				
			}

			
			if(value&&typeof value==="string"){
				
				classNames=value.split(rspace);				
				
				for(i=0,l=this.length;i<l;i++){
					
					elem=this[i];					
					
					if(elem.nodeType===1){
						
						if(!elem.className&&classNames.length===1){
							
							elem.className=value;							
							
							
						}else {
							
							setClass=" "+elem.className+" ";							
							
							for(c=0,cl=classNames.length;c<cl;c++){
								
								if(!~setClass.indexOf(" "+classNames[c]+" ")){
									
									setClass+=classNames[c]+" ";									
									
								}
								
							}

							elem.className=jQuery.trim(setClass);							
							
						}
						
					}
					
				}
				
			}

			
			return this;			
			
		},//#s3076-e3134
		
		/**
		 * 移除匹配元素的一个，多个或全部样式，作用与上面#s3076-e3134的addClass函数刚好相反
		 */
		removeClass:function (value){//#s3139-e3191
			
			var classNames,i,l,elem,className,c,cl;			
			
			if(jQuery.isFunction(value)){
				
				return this.each(function (j){
					
					jQuery(this).removeClass(value.call(this,j,this.className));					
					
				});				
				
			}

			
			if((value&&typeof value==="string")||value===undefined){
				
				classNames=(value||"").split(rspace);				
				
				for(i=0,l=this.length;i<l;i++){
					
					elem=this[i];					
					
					if(elem.nodeType===1&&elem.className){
						
						if(value){
							
							className=(" "+elem.className+" ").replace(rclass," ");							
							for(c=0,cl=classNames.length;c<cl;c++){
								
								className=className.replace(" "+classNames[c]+" "," ");								
								
							}

							elem.className=jQuery.trim(className);							
							
							
						}else {
							
							elem.className="";							
							
						}
						
					}
					
				}
				
			}

			
			return this;			
			
		},//#s3139-e3191
		
		/**
		 * 为匹配的元素交替切换样式名
		 */
		toggleClass:function (value,stateVal){//#s3196-e3249
			
			var type=typeof value,
			isBool=typeof stateVal==="boolean";			
			
			if(jQuery.isFunction(value)){
				
				return this.each(function (i){
					
					jQuery(this).toggleClass(value.call(this,i,this.className,stateVal),stateVal);					
					
				});				
				
			}

			
			return this.each(function (){
				
				if(type==="string"){
					
					// toggle individual class names
					var className,
					i=0,
					self=jQuery(this),
					state=stateVal,
					classNames=value.split(rspace);					
					
					while((className=classNames[i++])){
						
						// check each className given, space seperated list
						state=isBool?state:!self.hasClass(className);						
						self[state?"addClass":"removeClass"](className);						
						
					}
					
					
				}else if(type==="undefined"||type==="boolean"){
					
					if(this.className){
						
						// store className if set
						jQuery._data(this,"__className__",this.className);						
						
					}

					
					// toggle whole className
					this.className=this.className||value===false?"":jQuery._data(this,"__className__")||"";					
					
				}
				
			});			
			
		},//#s3196-e3249
		
		/**
		 * 检查判断匹配的元素是否含有某个特定的样式名。
		 */
		hasClass:function (selector){
			
			var className=" "+selector+" ";			
			for(var i=0,l=this.length;i<l;i++){
				
				if((" "+this[i].className+" ").replace(rclass," ").indexOf(className)>-1){
					
					return true;					
					
				}
				
			}

			
			return false;			
			
		},
		
		/**
		 * 主要用于获取和设置表单元素的值
		 * (1)获取：alert($('#abcd').val());(2)设置：$('#abcd').val('654321'); (3)请先在body中添加<input type="text" id="abcd" value="123456" />
		 */
		val:function (value){//#s3275-e3364
			
			var hooks,ret,
			elem=this[0];			
			
			if(!arguments.length){
				
				if(elem){
					
					hooks=jQuery.valHooks[elem.nodeName.toLowerCase()]||jQuery.valHooks[elem.type];					
					
					if(hooks&&"get" in hooks&&(ret=hooks.get(elem,"value"))!==undefined){
						
						return ret;						
						
					}

					
					ret=elem.value;					
					
					return typeof ret==="string"?
					// handle most common string cases
					ret.replace(rreturn,""):
					// handle cases where value is null/undef or number
					ret==null?"":ret;					
					
				}

				
				return undefined;				
				
			}

			
			var isFunction=jQuery.isFunction(value);			
			
			return this.each(function (i){
				
				var self=jQuery(this),val;				
				
				if(this.nodeType!==1){
					
					return ;					
					
				}

				
				if(isFunction){
					
					val=value.call(this,i,self.val());					
					
				}else {
					
					val=value;					
					
				}

				
				// Treat null/undefined as ""; convert numbers to string
				if(val==null){
					
					val="";					
					
				}else if(typeof val==="number"){
					
					val+="";					
					
				}else if(jQuery.isArray(val)){
					
					val=jQuery.map(val,function (value){
						
						return value==null?"":value+"";						
						
					});					
					
				}

				
				hooks=jQuery.valHooks[this.nodeName.toLowerCase()]||jQuery.valHooks[this.type];				
				
				// If set returns undefined, fall back to normal setting
				if(!hooks||!("set" in hooks)||hooks.set(this,val,"value")===undefined){
					
					this.value=val;					
					
				}
				
			});			
			
		}//#s3275-e3364
		
	});	//#s2779-e3121
	
	
	//1============================================================================================
	
	
	jQuery.extend({//#s3127-e3543
		
		valHooks:{
			
			option:{
				
				get:function (elem){
					
					// attributes.value is undefined in Blackberry 4.7 but
					// uses .value. See #6932
					var val=elem.attributes.value;					
					return !val||val.specified?elem.value:elem.text;					
					
				}
				
			},
			select:{
				
				get:function (elem){
					
					var value,
					index=elem.selectedIndex,
					values=[],
					options=elem.options,
					one=elem.type==="select-one";					
					
					// Nothing was selected
					if(index<0){
						
						return null;						
						
					}

					
					// Loop through all the selected options
					for(var i=one?index:0,max=one?index+1:options.length;i<max;i++){
						
						var option=options[i];						
						
						// Don't return options that are disabled or in a disabled
						// optgroup
						if(option.selected&&(jQuery.support.optDisabled?!option.disabled:option.getAttribute("disabled")===null)&&
						(!option.parentNode.disabled||!jQuery.nodeName(option.parentNode,"optgroup"))){
							
							
							// Get the specific value for the option
							value=jQuery(option).val();							
							
							// We don't need an array for one selects
							if(one){
								
								return value;								
								
							}

							
							// Multi-Selects return an array
							values.push(value);							
							
						}
						
					}

					
					// Fixes Bug #2551 -- select.val() broken in IE after
					// form.reset()
					if(one&&!values.length&&options.length){
						
						return jQuery(options[index]).val();						
						
					}

					
					return values;					
					
				},
				
				set:function (elem,value){
					
					var values=jQuery.makeArray(value);					
					
					jQuery(elem).find("option").each(function (){
						
						this.selected=jQuery.inArray(jQuery(this).val(),values)>=0;						
						
					});					
					
					if(!values.length){
						
						elem.selectedIndex=-1;						
						
					}

					return values;					
					
				}
				
			}
			
		},
		
		attrFn:{
			
			val:true,
			css:true,
			html:true,
			text:true,
			data:true,
			width:true,
			height:true,
			offset:true
			
		},
		
		attrFix:{
			
			// Always normalize to ensure hook usage
			tabindex:"tabIndex"
			
		},
		
		attr:function (elem,name,value,pass){
			
			var nType=elem.nodeType;			
			
			// don't get/set attributes on text, comment and attribute nodes
			if(!elem||nType===3||nType===8||nType===2){
				
				return undefined;				
				
			}

			
			if(pass&&name in jQuery.attrFn){
				
				return jQuery(elem)[name](value);				
				
			}

			
			// Fallback to prop when attributes are not supported
			if(!("getAttribute" in elem)){
				
				return jQuery.prop(elem,name,value);				
				
			}

			
			var ret,hooks,
			notxml=nType!==1||!jQuery.isXMLDoc(elem);			
			
			// Normalize the name if needed
			if(notxml){
				
				name=jQuery.attrFix[name]||name;				
				
				hooks=jQuery.attrHooks[name];				
				
				if(!hooks){
					
					// Use boolHook for boolean attributes
					if(rboolean.test(name)){
						
						
						hooks=boolHook;						
						
						// Use formHook for forms and if the name contains certain
						// characters
						
					}else if(formHook&&name!=="className"&&
					(jQuery.nodeName(elem,"form")||rinvalidChar.test(name))){
						
						
						hooks=formHook;						
						
					}
					
				}
				
			}

			
			if(value!==undefined){
				
				
				if(value===null){
					
					jQuery.removeAttr(elem,name);					
					return undefined;					
					
					
				}else if(hooks&&"set" in hooks&&notxml&&(ret=hooks.set(elem,value,name))!==undefined){
					
					return ret;					
					
					
				}else {
					
					elem.setAttribute(name,""+value);					
					return value;					
					
				}
				
				
			}else if(hooks&&"get" in hooks&&notxml&&(ret=hooks.get(elem,name))!==null){
				
				return ret;				
				
				
			}else {
				
				
				ret=elem.getAttribute(name);				
				
				// Non-existent attributes return null, we normalize to undefined
				return ret===null?
				undefined:
				ret;				
				
			}
			
		},
		
		removeAttr:function (elem,name){
			
			var propName;			
			if(elem.nodeType===1){
				
				name=jQuery.attrFix[name]||name;				
				
				if(jQuery.support.getSetAttribute){
					
					// Use removeAttribute in browsers that support it
					elem.removeAttribute(name);					
					
				}else {
					
					jQuery.attr(elem,name,"");					
					elem.removeAttributeNode(elem.getAttributeNode(name));					
					
				}

				
				// Set corresponding property to false for boolean attributes
				if(rboolean.test(name)&&(propName=jQuery.propFix[name]||name) in elem){
					
					elem[propName]=false;					
					
				}
				
			}
			
		},
		
		attrHooks:{
			
			type:{
				
				set:function (elem,value){
					
					// We can't allow the type property to be changed (since it
					// causes problems in IE)
					if(rtype.test(elem.nodeName)&&elem.parentNode){
						
						jQuery.error("type property can't be changed");						
						
					}else if(!jQuery.support.radioValue&&value==="radio"&&jQuery.nodeName(elem,"input")){
						
						// Setting the type on a radio button after the value resets
						// the value in IE6-9
						// Reset value to it's default in case type is set after
						// value
						// This is for element creation
						var val=elem.value;						
						elem.setAttribute("type",value);						
						if(val){
							
							elem.value=val;							
							
						}

						return value;						
						
					}
					
				}
				
			},
			tabIndex:{
				
				get:function (elem){
					
					// elem.tabIndex doesn't always return the correct value when it
					// hasn't been explicitly set
					// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
					var attributeNode=elem.getAttributeNode("tabIndex");					
					
					return attributeNode&&attributeNode.specified?
					parseInt(attributeNode.value,10):
					rfocusable.test(elem.nodeName)||rclickable.test(elem.nodeName)&&elem.href?
					0:
					undefined;					
					
				}
				
			},
			// Use the value property for back compat
			// Use the formHook for button elements in IE6/7 (#1954)
			value:{
				
				get:function (elem,name){
					
					if(formHook&&jQuery.nodeName(elem,"button")){
						
						return formHook.get(elem,name);						
						
					}

					return name in elem?
					elem.value:
					null;					
					
				},
				set:function (elem,value,name){
					
					if(formHook&&jQuery.nodeName(elem,"button")){
						
						return formHook.set(elem,value,name);						
						
					}

					// Does not return so that setAttribute is also used
					elem.value=value;					
					
				}
				
			}
			
		},
		
		propFix:{
			
			tabindex:"tabIndex",
			readonly:"readOnly",
			"for":"htmlFor",
			"class":"className",
			maxlength:"maxLength",
			cellspacing:"cellSpacing",
			cellpadding:"cellPadding",
			rowspan:"rowSpan",
			colspan:"colSpan",
			usemap:"useMap",
			frameborder:"frameBorder",
			contenteditable:"contentEditable"
			
		},
		
		prop:function (elem,name,value){
			
			var nType=elem.nodeType;			
			
			// don't get/set properties on text, comment and attribute nodes
			if(!elem||nType===3||nType===8||nType===2){
				
				return undefined;				
				
			}

			
			var ret,hooks,
			notxml=nType!==1||!jQuery.isXMLDoc(elem);			
			
			if(notxml){
				
				// Fix name and attach hooks
				name=jQuery.propFix[name]||name;				
				hooks=jQuery.propHooks[name];				
				
			}

			
			if(value!==undefined){
				
				if(hooks&&"set" in hooks&&(ret=hooks.set(elem,value,name))!==undefined){
					
					return ret;					
					
					
				}else {
					
					return (elem[name]=value);					
					
				}
				
				
			}else {
				
				if(hooks&&"get" in hooks&&(ret=hooks.get(elem,name))!==undefined){
					
					return ret;					
					
					
				}else {
					
					return elem[name];					
					
				}
				
			}
			
		},
		
		propHooks:{
			
		}
		
	});	//#s3127-e3543
	
	
	//1============================================================================================
	
	
	// Hook for boolean attributes
	boolHook={//#s3550-e3591
		
		get:function (elem,name){
			
			// Align boolean attributes with corresponding properties
			return jQuery.prop(elem,name)?
			name.toLowerCase():
			undefined;			
			
		},
		
		set:function (elem,value,name){
			
			var propName;			
			if(value===false){
				
				// Remove boolean attributes when set to false
				jQuery.removeAttr(elem,name);				
				
			}else {
				
				// value is true since we know at this point it's type boolean and
				// not false
				// Set boolean attributes to the same name and set the DOM property
				propName=jQuery.propFix[name]||name;				
				if(propName in elem){
					
					// Only set the IDL specifically if it already exists on the
					// element
					elem[propName]=true;					
					
				}

				
				elem.setAttribute(name,name.toLowerCase());				
				
			}

			return name;			
			
		}
		
	};	//#s3550-e3591
	
	
	//1============================================================================================
	
	
	// IE6/7 do not support getting/setting some attributes with get/setAttribute
	// 判断浏览器是否支持对属性的get/set操作，在IE6/7中有一些属性是不支持的
	if(!jQuery.support.getSetAttribute){//#s3598-e3654
		
		
		// propFix is more comprehensive and contains all fixes
		jQuery.attrFix=jQuery.propFix;		
		
		// Use this for any attribute on a form in IE6/7
		formHook=jQuery.attrHooks.name=jQuery.attrHooks.title=jQuery.valHooks.button={
			
			get:function (elem,name){
				
				var ret;				
				ret=elem.getAttributeNode(name);				
				// Return undefined if nodeValue is empty string
				return ret&&ret.nodeValue!==""?
				ret.nodeValue:
				undefined;				
				
			},
			set:function (elem,value,name){
				
				// Check form objects in IE (multiple bugs related)
				// Only use nodeValue if the attribute node exists on the form
				var ret=elem.getAttributeNode(name);				
				if(ret){
					
					ret.nodeValue=value;					
					return value;					
					
				}
				
			}
			
		};		
		
		// Set width and height to auto instead of 0 on empty string( Bug #8150 )
		// This is for removals
		jQuery.each(["width","height"],function (i,name){
			
			jQuery.attrHooks[name]=jQuery.extend(jQuery.attrHooks[name],{
				
				set:function (elem,value){
					
					if(value===""){
						
						elem.setAttribute(name,"auto");						
						return value;						
						
					}
					
				}
				
			});			
			
		});		
		
	}//#s3598-e3654
	
	
	//1============================================================================================
	
	
	// Some attributes require a special call on IE
	if(!jQuery.support.hrefNormalized){//#s3664-e3678
		
		jQuery.each(["href","src","width","height"],function (i,name){
			
			jQuery.attrHooks[name]=jQuery.extend(jQuery.attrHooks[name],{
				
				get:function (elem){
					
					var ret=elem.getAttribute(name,2);					
					return ret===null?undefined:ret;					
					
				}
				
			});			
			
		});		
		
	}//#s3664-e3678
	
	
	//1============================================================================================

	
	if(!jQuery.support.style){//#s3684-e3703
		
		jQuery.attrHooks.style={
			
			get:function (elem){
				
				// Return undefined in the case of empty string
				// Normalize to lowercase since IE uppercases css property names
				return elem.style.cssText.toLowerCase()||undefined;				
				
			},
			set:function (elem,value){
				
				return (elem.style.cssText=""+value);				
				
			}
			
		};		
		
	}//#s3684-e3703
	
	
	//1============================================================================================

	
	// Safari mis-reports the default selected property of an option
	// Accessing the parent's selectedIndex property fixes it
	if(!jQuery.support.optSelected){//#3711-3736
		
		jQuery.propHooks.selected=jQuery.extend(jQuery.propHooks.selected,{
			
			get:function (elem){
				
				var parent=elem.parentNode;				
				
				if(parent){
					
					parent.selectedIndex;					
					
					// Make sure that it also works with optgroups, see #5701
					if(parent.parentNode){
						
						parent.parentNode.selectedIndex;						
						
					}
					
				}
				
			}
			
		});		
		
	}//#3711-3736
	
	
	//1============================================================================================

	
	// Radios and checkboxes getter/setter
	if(!jQuery.support.checkOn){//#s3743-e3761
		
		jQuery.each(["radio","checkbox"],function (){
			
			jQuery.valHooks[this]={
				
				get:function (elem){
					
					// Handle the case where in Webkit "" is returned instead of
					// "on" if a value isn't specified
					return elem.getAttribute("value")===null?"on":elem.value;					
					
				}
				
			};			
			
		});		
		
	}//#s3743-e3761
	
	
	//1============================================================================================
	

	jQuery.each(["radio","checkbox"],function (){//#3767-e3783
		
		jQuery.valHooks[this]=jQuery.extend(jQuery.valHooks[this],{
			
			set:function (elem,value){
				
				if(jQuery.isArray(value)){
					
					return (elem.checked=jQuery.inArray(jQuery(elem).val(),value)>=0);					
					
				}
				
			}
			
		});		
		
	});	//#3767-e3783
	
	
	//1============================================================================================
	
	
	//匹配：.符号后跟任意的字符串，即包含有.符号的任意字符串
	var rnamespaces=/\.(.*)$/,
	//匹配：表单元素，
	rformElems=/^(?:textarea|input|select)$/i,
	rperiod=/\./g,//匹配：全局匹配.符号
	rspaces=/ /g,//匹配：全局匹配一个空格符号
	rescape=/[^\w\s.|`]/g,
	fcleanup=function (nm){
		
		return nm.replace(rescape,"\\$&");		
		
	};	
	
	
	//1============================================================================================
	
	
	/*
	 * A number of helper functions used for managing events. Many of the ideas
	 * behind this code originated from Dean Edwards' addEvent library.
	 */
	jQuery.event={//#s3808-e4608
		
		
		// Bind an event to an element
		// Original by Dean Edwards
		add:function (elem,types,handler,data){//#s4063-e4243
			
			if(elem.nodeType===3||elem.nodeType===8){
				
				return ;				
				
			}

			
			if(handler===false){
				
				handler=returnFalse;				
				
			}else if(!handler){
				
				// Fixes bug #7229. Fix recommended by jdalton
				return ;				
				
			}

			
			var handleObjIn,handleObj;			
			
			if(handler.handler){
				
				handleObjIn=handler;				
				handler=handleObjIn.handler;				
				
			}

			
			// Make sure that the function being executed has a unique ID
			if(!handler.guid){
				
				handler.guid=jQuery.guid++;				
				
			}

			
			// Init the element's event structure
			var elemData=jQuery._data(elem);			
			
			// If no elemData is found then we must be trying to bind to one of the
			// banned noData elements
			if(!elemData){
				
				return ;				
				
			}

			
			var events=elemData.events,
			eventHandle=elemData.handle;			
			
			if(!events){
				
				elemData.events=events={
					
				};				
				
			}

			
			if(!eventHandle){
				
				elemData.handle=eventHandle=function (e){
					
					// Discard the second event of a jQuery.event.trigger() and
					// when an event is called after a page has unloaded
					return typeof jQuery!=="undefined"&&(!e||jQuery.event.triggered!==e.type)?
					jQuery.event.handle.apply(eventHandle.elem,arguments):
					undefined;					
					
				};				
				
			}

			
			// Add elem as a property of the handle function
			// This is to prevent a memory leak with non-native events in IE.
			eventHandle.elem=elem;			
			
			// Handle multiple events separated by a space
			// jQuery(...).bind("mouseover mouseout", fn);
			types=types.split(" ");			
			
			var type,i=0,namespaces;			
			
			while((type=types[i++])){
				
				handleObj=handleObjIn?
				jQuery.extend({
					
				},handleObjIn):
				{
					handler:handler,data:data
				};				
				
				// Namespaced event handlers
				if(type.indexOf(".")>-1){
					
					namespaces=type.split(".");					
					type=namespaces.shift();					
					handleObj.namespace=namespaces.slice(0).sort().join(".");					
					
					
				}else {
					
					namespaces=[];					
					handleObj.namespace="";					
					
				}

				
				handleObj.type=type;				
				if(!handleObj.guid){
					
					handleObj.guid=handler.guid;					
					
				}

				
				// Get the current list of functions bound to this event
				var handlers=events[type],
				special=jQuery.event.special[type]||{
					
				};				
				
				// Init the event handler queue
				if(!handlers){
					
					handlers=events[type]=[];					
					
					// Check for a special event handler
					// Only use addEventListener/attachEvent if the special
					// events handler returns false
					if(!special.setup||special.setup.call(elem,data,namespaces,eventHandle)===false){
						
						// Bind the global event handler to the element
						if(elem.addEventListener){
							
							elem.addEventListener(type,eventHandle,false);							
							
							
						}else if(elem.attachEvent){
							
							elem.attachEvent("on"+type,eventHandle);							
							
						}
						
					}
					
				}

				
				if(special.add){
					
					special.add.call(elem,handleObj);					
					
					if(!handleObj.handler.guid){
						
						handleObj.handler.guid=handler.guid;						
						
					}
					
				}

				
				// Add the function to the element's handler list
				handlers.push(handleObj);				
				
				// Keep track of which events have been used, for event optimization
				jQuery.event.global[type]=true;				
				
			}

			
			// Nullify elem to prevent memory leaks in IE
			elem=null;			
			
		},//#s4063-e4243
		
		global:{
			
		},
		
		// Detach an event or set of events from an element
		remove:function (elem,types,handler,pos){//#s4250-e4437
			
			// don't do events on text and comment nodes
			if(elem.nodeType===3||elem.nodeType===8){
				
				return ;				
				
			}

			
			if(handler===false){
				
				handler=returnFalse;				
				
			}

			
			var ret,type,fn,j,i=0,all,namespaces,namespace,special,eventType,handleObj,origType,
			elemData=jQuery.hasData(elem)&&jQuery._data(elem),
			events=elemData&&elemData.events;			
			
			if(!elemData||!events){
				
				return ;				
				
			}

			
			// types is actually an event object here
			if(types&&types.type){
				
				handler=types.handler;				
				types=types.type;				
				
			}

			
			// Unbind all events for the element
			if(!types||typeof types==="string"&&types.charAt(0)==="."){
				
				types=types||"";				
				
				for(type in events){
					
					jQuery.event.remove(elem,type+types);					
					
				}

				
				return ;				
				
			}

			
			// Handle multiple events separated by a space
			// jQuery(...).unbind("mouseover mouseout", fn);
			types=types.split(" ");			
			
			while((type=types[i++])){
				
				origType=type;				
				handleObj=null;				
				all=type.indexOf(".")<0;				
				namespaces=[];				
				
				if(!all){
					
					// Namespaced event handlers
					namespaces=type.split(".");					
					type=namespaces.shift();					
					
					namespace=new RegExp("(^|\\.)"+
					jQuery.map(namespaces.slice(0).sort(),fcleanup).join("\\.(?:.*\\.)?")+"(\\.|$)");					
					
				}

				
				eventType=events[type];				
				
				if(!eventType){
					
					continue;					
					
				}

				
				if(!handler){
					
					for(j=0;j<eventType.length;j++){
						
						handleObj=eventType[j];						
						
						if(all||namespace.test(handleObj.namespace)){
							
							jQuery.event.remove(elem,origType,handleObj.handler,j);							
							eventType.splice(j--,1);							
							
						}
						
					}

					
					continue;					
					
				}

				
				special=jQuery.event.special[type]||{
					
				};				
				
				for(j=pos||0;j<eventType.length;j++){
					
					handleObj=eventType[j];					
					
					if(handler.guid===handleObj.guid){
						
						// remove the given handler for the given type
						if(all||namespace.test(handleObj.namespace)){
							
							if(pos==null){
								
								eventType.splice(j--,1);								
								
							}

							
							if(special.remove){
								
								special.remove.call(elem,handleObj);								
								
							}
							
						}

						
						if(pos!=null){
							
							break;							
							
						}
						
					}
					
				}

				
				// remove generic event handler if no more handlers exist
				if(eventType.length===0||pos!=null&&eventType.length===1){
					
					if(!special.teardown||special.teardown.call(elem,namespaces)===false){
						
						jQuery.removeEvent(elem,type,elemData.handle);						
						
					}

					
					ret=null;					
					delete events[type];					
					
				}
				
			}

			
			// Remove the expando if it's no longer used
			if(jQuery.isEmptyObject(events)){
				
				var handle=elemData.handle;				
				if(handle){
					
					handle.elem=null;					
					
				}

				
				delete elemData.events;				
				delete elemData.handle;				
				
				if(jQuery.isEmptyObject(elemData)){
					
					jQuery.removeData(elem,undefined,true);					
					
				}
				
			}
			
		},//#s4250-e4437
		
		// Events that are safe to short-circuit if no handlers are attached.
		// Native DOM events should not be added, they may have inline handlers.
		customEvent:{
			
			"getData":true,
			"setData":true,
			"changeData":true
			
		},
		
		trigger:function (event,data,elem,onlyHandlers){//#s4449-e4640
			
			// Event object or event type
			var type=event.type||event,
			namespaces=[],
			exclusive;			
			
			if(type.indexOf("!")>=0){
				
				// Exclusive events trigger only for the exact event (no namespaces)
				type=type.slice(0,-1);				
				exclusive=true;				
				
			}

			
			if(type.indexOf(".")>=0){
				
				// Namespaced trigger; create a regexp to match event type in
				// handle()
				namespaces=type.split(".");				
				type=namespaces.shift();				
				namespaces.sort();				
				
			}

			
			if((!elem||jQuery.event.customEvent[type])&&!jQuery.event.global[type]){
				
				// No jQuery handlers for this event type, and it can't have inline
				// handlers
				return ;				
				
			}

			
			// Caller can pass in an Event, Object, or just an event type string
			event=typeof event==="object"?
			// jQuery.Event object
			event[jQuery.expando]?event:
			// Object literal
			new jQuery.Event(type,event):
			// Just the event type (string)
			new jQuery.Event(type);			
			
			event.type=type;			
			event.exclusive=exclusive;			
			event.namespace=namespaces.join(".");			
			event.namespace_re=new RegExp("(^|\\.)"+namespaces.join("\\.(?:.*\\.)?")+"(\\.|$)");			
			
			// triggerHandler() and global events don't bubble or run the default
			// action
			if(onlyHandlers||!elem){
				
				event.preventDefault();				
				event.stopPropagation();				
				
			}

			
			// Handle a global trigger
			if(!elem){
				
				// TODO: Stop taunting the data cache; remove global events and
				// always attach to document
				jQuery.each(jQuery.cache,function (){
					
					// internalKey variable is just used to make it easier to find
					// and potentially change this stuff later; currently it just
					// points to jQuery.expando
					var internalKey=jQuery.expando,
					internalCache=this[internalKey];					
					if(internalCache&&internalCache.events&&internalCache.events[type]){
						
						jQuery.event.trigger(event,data,internalCache.handle.elem);						
						
					}
					
				});				
				return ;				
				
			}

			
			// Don't do events on text and comment nodes
			if(elem.nodeType===3||elem.nodeType===8){
				
				return ;				
				
			}

			
			// Clean up the event in case it is being reused
			event.result=undefined;			
			event.target=elem;			
			
			// Clone any incoming data and prepend the event, creating the handler
			// arg list
			data=data!=null?jQuery.makeArray(data):[];			
			data.unshift(event);			
			
			var cur=elem,
			// IE doesn't like method names with a colon (#3533, #8272)
			ontype=type.indexOf(":")<0?"on"+type:"";			
			
			// Fire event on the current element, then bubble up the DOM tree
			do{
				
				var handle=jQuery._data(cur,"handle");				
				
				event.currentTarget=cur;				
				if(handle){
					
					handle.apply(cur,data);					
					
				}

				
				// Trigger an inline bound script
				if(ontype&&jQuery.acceptData(cur)&&cur[ontype]&&cur[ontype].apply(cur,data)===false){
					
					event.result=false;					
					event.preventDefault();					
					
				}

				
				// Bubble up to document, then to window
				cur=cur.parentNode||cur.ownerDocument||cur===event.target.ownerDocument&&window;				
				
			}while(cur&&!event.isPropagationStopped());			
			
			// If nobody prevented the default action, do it now
			if(!event.isDefaultPrevented()){
				
				var old,
				special=jQuery.event.special[type]||{
					
				};				
				
				if((!special._default||special._default.call(elem.ownerDocument,event)===false)&&
				!(type==="click"&&jQuery.nodeName(elem,"a"))&&jQuery.acceptData(elem)){
					
					
					// Call a native DOM method on the target with the same name
					// name as the event.
					// Can't use an .isFunction)() check here because IE6/7 fails
					// that test.
					// IE<9 dies on focus to hidden element (#1486), may want to
					// revisit a try/catch.
					try{
						
						if(ontype&&elem[type]){
							
							// Don't re-trigger an onFOO event when we call its
							// FOO() method
							old=elem[ontype];							
							
							if(old){
								
								elem[ontype]=null;								
								
							}

							
							jQuery.event.triggered=type;							
							elem[type]();							
							
						}
						
					}catch(ieError){
						
					}

					
					if(old){
						
						elem[ontype]=old;						
						
					}

					
					jQuery.event.triggered=undefined;					
					
				}
				
			}

			
			return event.result;			
			
		},//#s4449-e4640
		
		handle:function (event){//#s4642-e4700
			
			event=jQuery.event.fix(event||window.event);			
			// Snapshot the handlers list since a called handler may add/remove
			// events.
			var handlers=((jQuery._data(this,"events")||{
				
			})[event.type]||[]).slice(0),
			run_all=!event.exclusive&&!event.namespace,
			args=Array.prototype.slice.call(arguments,0);			
			
			// Use the fix-ed Event rather than the (read-only) native event
			args[0]=event;			
			event.currentTarget=this;			
			
			for(var j=0,l=handlers.length;j<l;j++){
				
				var handleObj=handlers[j];				
				
				// Triggered event must 1) be non-exclusive and have no namespace,
				// or
				// 2) have namespace(s) a subset or equal to those in the bound
				// event.
				if(run_all||event.namespace_re.test(handleObj.namespace)){
					
					// Pass in a reference to the handler function itself
					// So that we can later remove it
					event.handler=handleObj.handler;					
					event.data=handleObj.data;					
					event.handleObj=handleObj;					
					
					var ret=handleObj.handler.apply(this,args);					
					
					if(ret!==undefined){
						
						event.result=ret;						
						if(ret===false){
							
							event.preventDefault();							
							event.stopPropagation();							
							
						}
						
					}

					
					if(event.isImmediatePropagationStopped()){
						
						break;						
						
					}
					
				}
				
			}

			return event.result;			
			
		},//#s4642-e4700
		
		props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
		
		fix:function (event){//#s4704-e4791
			
			if(event[jQuery.expando]){
				
				return event;				
				
			}

			
			// store a copy of the original event object
			// and "clone" to set read-only properties
			var originalEvent=event;			
			event=jQuery.Event(originalEvent);			
			
			for(var i=this.props.length,prop;i;){
				
				prop=this.props[--i];				
				event[prop]=originalEvent[prop];				
				
			}

			
			// Fix target property, if necessary
			if(!event.target){
				
				// Fixes #1925 where srcElement might not be defined either
				event.target=event.srcElement||document;				
				
			}

			
			// check if target is a textnode (safari)
			if(event.target.nodeType===3){
				
				event.target=event.target.parentNode;				
				
			}

			
			// Add relatedTarget, if necessary
			if(!event.relatedTarget&&event.fromElement){
				
				event.relatedTarget=event.fromElement===event.target?event.toElement:event.fromElement;				
				
			}

			
			// Calculate pageX/Y if missing and clientX/Y available
			if(event.pageX==null&&event.clientX!=null){
				
				var eventDocument=event.target.ownerDocument||document,
				doc=eventDocument.documentElement,
				body=eventDocument.body;				
				
				event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc&&doc.clientLeft||body&&body.clientLeft||0);				
				event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc&&doc.clientTop||body&&body.clientTop||0);				
				
			}

			
			// Add which for key events
			if(event.which==null&&(event.charCode!=null||event.keyCode!=null)){
				
				event.which=event.charCode!=null?event.charCode:event.keyCode;				
				
			}

			
			// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
			if(!event.metaKey&&event.ctrlKey){
				
				event.metaKey=event.ctrlKey;				
				
			}

			
			// Add which for click: 1 === left; 2 === middle; 3 === right
			// Note: button is not normalized, so don't use it
			if(!event.which&&event.button!==undefined){
				
				event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)));				
				
			}

			
			return event;			
			
		},//#s4704-e4791
		
		// Deprecated, use jQuery.guid instead
		guid:1E8,
		
		// Deprecated, use jQuery.proxy instead
		proxy:jQuery.proxy,
		
		special:{//#s4799-e4856
			
			ready:{
				
				// Make sure the ready event is setup
				setup:jQuery.bindReady,
				teardown:jQuery.noop
				
			},
			
			live:{
				
				add:function (handleObj){
					
					jQuery.event.add(this,
					liveConvert(handleObj.origType,handleObj.selector),
					jQuery.extend({
						
					},handleObj,{
						handler:liveHandler,guid:handleObj.handler.guid
					}));					
					
				},
				
				remove:function (handleObj){
					
					jQuery.event.remove(this,liveConvert(handleObj.origType,handleObj.selector),handleObj);					
					
				}
				
			},
			
			beforeunload:{
				
				setup:function (data,namespaces,eventHandle){
					
					// We only want to do this special case on windows
					if(jQuery.isWindow(this)){
						
						this.onbeforeunload=eventHandle;						
						
					}
					
				},
				
				teardown:function (namespaces,eventHandle){
					
					if(this.onbeforeunload===eventHandle){
						
						this.onbeforeunload=null;						
						
					}
					
				}
				
			}
			
		}//#s4799-e4856
		
	};	//#s3808-e4608
	
	
	//1============================================================================================
	
	
	//兼容IE和FF，注销删除为匹配元素注册的执行函数事件．也就是说删除网页中或某个元素的执行函数
	//注意：如果你直接使用onclick或onkeyup直接写在元素内的事件．将无法使用jQuery.removeEvent来删除．
	jQuery.removeEvent=document.removeEventListener?
	function (elem,type,handle){
		
		if(elem.removeEventListener){
			
			elem.removeEventListener(type,handle,false);			
			
		}
		
	}
:
	function (elem,type,handle){
		
		if(elem.detachEvent){
			
			elem.detachEvent("on"+type,handle);			
			
		}
		
	};
	
	
	//1============================================================================================
	
	
	jQuery.Event=function (src,props){//#s4639-e4684
		
		// Allow instantiation without the 'new' keyword
		if(!this.preventDefault){
			
			return new jQuery.Event(src,props);			
			
		}

		
		// Event object
		if(src&&src.type){
			
			this.originalEvent=src;			
			this.type=src.type;			
			
			// Events bubbling up the document may have been marked as prevented
			// by a handler lower down the tree; reflect the correct value.
			this.isDefaultPrevented=(src.defaultPrevented||src.returnValue===false||
			src.getPreventDefault&&src.getPreventDefault())?returnTrue:returnFalse;			
			
			// Event type
			
		}else {
			
			this.type=src;			
			
		}

		
		// Put explicitly provided properties onto the event object
		if(props){
			
			jQuery.extend(this,props);			
			
		}

		
		// timeStamp is buggy for some events on Firefox(#3843)
		// So we won't rely on the native value
		this.timeStamp=jQuery.now();		
		
		// Mark it as fixed
		this[jQuery.expando]=true;		
		
	};//#s4639-e4684
	
	
	//1============================================================================================
	
	
	function returnFalse(){
		
		return false;		
		
	}

	function returnTrue(){
		
		return true;		
		
	}
	
	
	//1============================================================================================

	
	// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language
	// Binding
	// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
	jQuery.Event.prototype={//#s4709-e4771
		
		//阻止默认事件行为的触发。
		preventDefault:function (){
			
			this.isDefaultPrevented=returnTrue;			
			
			var e=this.originalEvent;			
			if(!e){
				
				return ;				
				
			}

			
			// if preventDefault exists run it on the original event
			if(e.preventDefault){
				
				e.preventDefault();				
				
				// otherwise set the returnValue property of the original event to false
				// (IE)
				
			}else {
				
				e.returnValue=false;				
				
			}
			
		},
		
		//防止事件冒泡到DOM树上，也就是不触发的任何前辈元素上的事件处理函数。
		stopPropagation:function (){
			
			this.isPropagationStopped=returnTrue;			
			
			var e=this.originalEvent;			
			if(!e){
				
				return ;				
				
			}

			// if stopPropagation exists run it on the original event
			if(e.stopPropagation){
				
				e.stopPropagation();				
				
			}

			// otherwise set the cancelBubble property of the original event to true
			// (IE)
			e.cancelBubble=true;			
			
		},
		
		//阻止剩余的事件处理函数执行并且防止事件冒泡到DOM树上。即除了阻止元素上其它的事件处理函数的执行，这个方法还会通过在内部调用 event.stopPropagation() 来停止事件冒泡。
		stopImmediatePropagation:function (){
			
			this.isImmediatePropagationStopped=returnTrue;			
			this.stopPropagation();			
			
		},
		
		isDefaultPrevented:returnFalse,
		isPropagationStopped:returnFalse,
		isImmediatePropagationStopped:returnFalse
		
	};//#s4709-e4771	
	
	
	//1============================================================================================
	
	
	// Checks if an event happened on an element within another element
	// Used in jQuery.event.special.mouseenter and mouseleave handlers
	var withinElement=function (event){
		
		
		// Check if mouse(over|out) are still within the same parent element
		var related=event.relatedTarget,
		inside=false,
		eventType=event.type;		
		
		event.type=event.data;		
		
		if(related!==this){
			
			
			if(related){
				
				inside=jQuery.contains(this,related);				
				
			}

			
			if(!inside){
				
				
				jQuery.event.handle.apply(this,arguments);				
				
				event.type=eventType;				
				
			}
			
		}
		
	},
	
	// In case of event delegation, we only need to rename the event.type,
	// liveHandler will take care of the rest.
	delegate=function (event){
		
		event.type=event.data;		
		jQuery.event.handle.apply(this,arguments);		
		
	};
	
	
	//1============================================================================================	
	
	
	// Create mouseenter and mouseleave events
	jQuery.each({//#s4826-e4848
		
		mouseenter:"mouseover",
		mouseleave:"mouseout"
		
	},function (orig,fix){
		
		jQuery.event.special[orig]={
			
			setup:function (data){
				
				jQuery.event.add(this,fix,data&&data.selector?delegate:withinElement,orig);				
				
			},
			teardown:function (data){
				
				jQuery.event.remove(this,fix,data&&data.selector?delegate:withinElement);				
				
			}
			
		};		
		
	});	//#s4826-e4848
	
	
	//1============================================================================================	
	
	
	// submit delegation
	if(!jQuery.support.submitBubbles){//#s4855-e4908
		
		
		jQuery.event.special.submit={
			
			setup:function (data,namespaces){
				
				if(!jQuery.nodeName(this,"form")){
					
					jQuery.event.add(this,"click.specialSubmit",function (e){
						
						var elem=e.target,
						type=elem.type;						
						
						if((type==="submit"||type==="image")&&jQuery(elem).closest("form").length){
							
							trigger("submit",this,arguments);							
							
						}
						
					});					
					
					jQuery.event.add(this,"keypress.specialSubmit",function (e){
						
						var elem=e.target,
						type=elem.type;						
						
						if((type==="text"||type==="password")&&jQuery(elem).closest("form").length&&e.keyCode===13){
							
							trigger("submit",this,arguments);							
							
						}
						
					});					
					
					
				}else {
					
					return false;					
					
				}
				
			},
			
			teardown:function (namespaces){
				
				jQuery.event.remove(this,".specialSubmit");				
				
			}
			
		};		
		
		
	}//#s4855-e4908
	
	
	//1============================================================================================	

	
	// change delegation, happens here so we have bind.
	if(!jQuery.support.changeBubbles){//#s4915-e5076
		
		
		var changeFilters,
		
		getVal=function (elem){
			
			var type=elem.type,val=elem.value;			
			
			if(type==="radio"||type==="checkbox"){
				
				val=elem.checked;				
				
				
			}else if(type==="select-multiple"){
				
				val=elem.selectedIndex>-1?
				jQuery.map(elem.options,function (elem){
					
					return elem.selected;					
					
				}).join("-"):
				"";				
				
				
			}else if(jQuery.nodeName(elem,"select")){
				
				val=elem.selectedIndex;				
				
			}

			
			return val;			
			
		},
		
		testChange=function testChange(e){
			
			var elem=e.target,data,val;			
			
			if(!rformElems.test(elem.nodeName)||elem.readOnly){
				
				return ;				
				
			}

			
			data=jQuery._data(elem,"_change_data");			
			val=getVal(elem);			
			
			// the current data will be also retrieved by beforeactivate
			if(e.type!=="focusout"||elem.type!=="radio"){
				
				jQuery._data(elem,"_change_data",val);				
				
			}

			
			if(data===undefined||val===data){
				
				return ;				
				
			}

			
			if(data!=null||val){
				
				e.type="change";				
				e.liveFired=undefined;				
				jQuery.event.trigger(e,arguments[1],elem);				
				
			}
			
		};		
		
		jQuery.event.special.change={
			
			filters:{
				
				focusout:testChange,
				
				beforedeactivate:testChange,
				
				click:function (e){
					
					var elem=e.target,type=jQuery.nodeName(elem,"input")?elem.type:"";					
					
					if(type==="radio"||type==="checkbox"||jQuery.nodeName(elem,"select")){
						
						testChange.call(this,e);						
						
					}
					
				},
				
				// Change has to be called before submit
				// Keydown will be called before keypress, which is used in
				// submit-event delegation
				keydown:function (e){
					
					var elem=e.target,type=jQuery.nodeName(elem,"input")?elem.type:"";					
					
					if((e.keyCode===13&&!jQuery.nodeName(elem,"textarea"))||
					(e.keyCode===32&&(type==="checkbox"||type==="radio"))||
					type==="select-multiple"){
						
						testChange.call(this,e);						
						
					}
					
				},
				
				// Beforeactivate happens also before the previous element is
				// blurred
				// with this event you can't trigger a change event, but you can
				// store
				// information
				beforeactivate:function (e){
					
					var elem=e.target;					
					jQuery._data(elem,"_change_data",getVal(elem));					
					
				}
				
			},
			
			setup:function (data,namespaces){
				
				if(this.type==="file"){
					
					return false;					
					
				}

				
				for(var type in changeFilters){
					
					jQuery.event.add(this,type+".specialChange",changeFilters[type]);					
					
				}

				
				return rformElems.test(this.nodeName);				
				
			},
			
			teardown:function (namespaces){
				
				jQuery.event.remove(this,".specialChange");				
				
				return rformElems.test(this.nodeName);				
				
			}
			
		};		
		
		changeFilters=jQuery.event.special.change.filters;		
		
		// Handle when the input is .focus()'d
		changeFilters.focus=changeFilters.beforeactivate;		
		
	}//#s4915-e5076
	
	
	//1============================================================================================	

	//将给定的事件类型执行所有处理和行为附加到匹配的元素
	function trigger(type,elem,args){//#s5082-e5103
		
		// Piggyback on a donor event to simulate a different one.
		// Fake originalEvent to avoid donor's stopPropagation, but if the
		// simulated event prevents default then we do the same on the donor.
		// Don't pass args or remember liveFired; they apply to the donor event.
		var event=jQuery.extend({
			
		},args[0]);		
		event.type=type;		
		event.originalEvent={
			
		};		
		event.liveFired=undefined;		
		jQuery.event.handle.call(elem,event);		
		if(event.isDefaultPrevented()){
			
			args[0].preventDefault();			
			
		}
		
	}//#s5082-e5103
	
	
	//1============================================================================================	

	
	// Create "bubbling" focus and blur events
	if(!jQuery.support.focusinBubbles){//#s5110-e5164
		
		jQuery.each({
			focus:"focusin",blur:"focusout"
		},function (orig,fix){
			
			
			// Attach a single capturing handler while someone wants
			// focusin/focusout
			var attaches=0;			
			
			jQuery.event.special[fix]={
				
				setup:function (){
					
					if(attaches++===0){
						
						document.addEventListener(orig,handler,true);						
						
					}
					
				},
				teardown:function (){
					
					if(--attaches===0){
						
						document.removeEventListener(orig,handler,true);						
						
					}
					
				}
				
			};			
			
			function handler(donor){
				
				// Donor event is always a native one; fix it and switch its type.
				// Let focusin/out handler cancel the donor focus/blur event.
				var e=jQuery.event.fix(donor);				
				e.type=fix;				
				e.originalEvent={
					
				};				
				jQuery.event.trigger(e,null,e.target);				
				if(e.isDefaultPrevented()){
					
					donor.preventDefault();					
					
				}
				
			}
			
		});		
		
	}//#s5110-e5164
	
	
	//1============================================================================================	

	/**
	 * 这里为jQuery增加了两个非常有用的方法：
	 * (1)bind方法：为匹配的元素添加绑定一个处理事件。示例：$('#foo').bind('click', function(){alert('User clicked on "foo."');});
	 * (2)one方法：附加一个处理事件到元素，处理函数在每个元素上最多执行一次。示例：$('#foo').one('click', function(){alert('This will be displayed only once.');});
	 */
	jQuery.each(["bind","one"],function (i,name){//#s5170-e5235
		
		jQuery.fn[name]=function (type,data,fn){
			
			var handler;			
			
			// Handle object literals
			if(typeof type==="object"){
				
				for(var key in type){
					
					this[name](key,data,type[key],fn);					
					
				}

				return this;				
				
			}

			
			if(arguments.length===2||data===false){
				
				fn=data;				
				data=undefined;				
				
			}

			
			if(name==="one"){
				
				handler=function (event){
					
					jQuery(this).unbind(event,handler);					
					return fn.apply(this,arguments);					
					
				};				
				handler.guid=fn.guid||jQuery.guid++;				
				
			}else {
				
				handler=fn;				
				
			}

			
			if(type==="unload"&&name!=="one"){
				
				this.one(type,data,fn);				
				
				
			}else {
				
				for(var i=0,l=this.length;i<l;i++){
					
					jQuery.event.add(this[i],type,handler,data);					
					
				}
				
			}

			
			return this;			
			
		};		
		
	});//#s5170-e5235
	
	
	//1============================================================================================	
	
	
	jQuery.fn.extend({//#s5241-e5350
		
		//从匹配元素上解除之前绑定的事件处理程序，与上面#s5170-e5235的bind方法的作用刚好相反
		//示例：(1)绑定事件：$('#foo').bind('click', function(){alert('do bind');});(2)解除绑定：$('#foo').unbind('click', function(){alert('do unbind');});
		unbind:function (type,fn){
			
			// Handle object literals
			if(typeof type==="object"&&!type.preventDefault){
				
				for(var key in type){
					
					this.unbind(key,type[key]);					
					
				}
				
				
			}else {
				
				for(var i=0,l=this.length;i<l;i++){
					
					jQuery.event.remove(this[i],type,fn);					
					
				}
				
			}

			
			return this;			
			
		},
		
		//为所有选择器匹配的元素附加一个或多个处理事件，现在或将来，基于一组特定的根元素。
		//示例：$("body").delegate("p", "click", function(){$(this).after("<p>Another paragraph!</p>");});
		delegate:function (selector,types,data,fn){
			
			return this.live(types,data,fn,selector);			
			
		},
		
		//为当前选择所匹配的所有元素移除一个事件处理程序，现在或将来，基于一组特定的根元素。与上面的delegate方法的作用刚好相反
		//示例：
		undelegate:function (selector,types,fn){
			
			if(arguments.length===0){
				
				return this.unbind("live");				
				
				
			}else {
				
				return this.die(types,null,fn,selector);				
				
			}
			
		},
		
		//将给定的事件类型执行所有处理和行为附加到匹配的元素
		//示例：
		trigger:function (type,data){
			
			return this.each(function (){
				
				jQuery.event.trigger(type,data,this);				
				
			});			
			
		},
		
		//此方法作用类似于上面的trigger方法
		triggerHandler:function (type,data){
			
			if(this[0]){
				
				return jQuery.event.trigger(type,data,this[0],true);				
				
			}
			
		},
		
		//交替显示或隐藏匹配元素。
		toggle:function (fn){
			
			// Save reference to arguments for access in closure
			var args=arguments,
			guid=fn.guid||jQuery.guid++,
			i=0,
			toggler=function (event){
				
				// Figure out which function to execute
				var lastToggle=(jQuery.data(this,"lastToggle"+fn.guid)||0)%i;				
				jQuery.data(this,"lastToggle"+fn.guid,lastToggle+1);				
				
				// Make sure that clicks stop
				event.preventDefault();				
				
				// and execute the function
				return args[lastToggle].apply(this,arguments)||false;				
				
			};			
			
			// link all the functions, so any of them can unbind this click handler
			toggler.guid=guid;			
			while(i<args.length){
				
				args[i++].guid=guid;				
				
			}

			
			return this.click(toggler);			
			
		},
		
		//将二个事件函数绑定到匹配元素上，分别当鼠标指针进入和离开元素时被执行。
		hover:function (fnOver,fnOut){
			
			return this.mouseenter(fnOver).mouseleave(fnOut||fnOver);			
			
		}
		
	});	//#s5241-e5350
	
	
	//1============================================================================================	
	
	
	var liveMap={
		
		focus:"focusin",
		blur:"focusout",
		mouseenter:"mouseover",
		mouseleave:"mouseout"
		
	};
	
	
	//1============================================================================================	
	

	/**
	 * 这里为jQuery增加了两个方法：
	 * (1)live方法：附加一个事件处理到符合匹配目前选择器的所有元素，注意与bind方法的区别。示例：$("p").live("click", function(){alert( $(this).text() );});
	 * (2)die方法：从匹配元素中删除先前用.live()绑定的所有事件，任何通过.live()附加的处理器都可以使用.die()删除，注意与unbind方法的区别。示例：$("p").die("click", function(){alert( $(this).text() );});
	 */
	jQuery.each(["live","die"],function (i,name){//#s5369-e5478
		
		jQuery.fn[name]=function (types,data,fn,origSelector/*
																		 * Internal Use
																		 * Only
																		 */){
			
			var type,i=0,match,namespaces,preType,
			selector=origSelector||this.selector,
			context=origSelector?this:jQuery(this.context);			
			
			if(typeof types==="object"&&!types.preventDefault){
				
				for(var key in types){
					
					context[name](key,data,types[key],selector);					
					
				}

				
				return this;				
				
			}

			
			if(name==="die"&&!types&&
			origSelector&&origSelector.charAt(0)==="."){
				
				
				context.unbind(origSelector);				
				
				return this;				
				
			}

			
			if(data===false||jQuery.isFunction(data)){
				
				fn=data||returnFalse;				
				data=undefined;				
				
			}

			
			types=(types||"").split(" ");			
			
			while((type=types[i++])!=null){
				
				match=rnamespaces.exec(type);				
				namespaces="";				
				
				if(match){
					
					namespaces=match[0];					
					type=type.replace(rnamespaces,"");					
					
				}

				
				if(type==="hover"){
					
					types.push("mouseenter"+namespaces,"mouseleave"+namespaces);					
					continue;					
					
				}

				
				preType=type;				
				
				if(liveMap[type]){
					
					types.push(liveMap[type]+namespaces);					
					type=type+namespaces;					
					
					
				}else {
					
					type=(liveMap[type]||type)+namespaces;					
					
				}

				
				if(name==="live"){
					
					// bind live handler
					for(var j=0,l=context.length;j<l;j++){
						
						jQuery.event.add(context[j],"live."+liveConvert(type,selector),
						{
							data:data,selector:selector,handler:fn,origType:type,origHandler:fn,preType:preType
						});						
						
					}
					
					
				}else {
					
					// unbind live handler
					context.unbind("live."+liveConvert(type,selector),fn);					
					
				}
				
			}

			
			return this;			
			
		};		
		
	});	//#s5369-e5478
	
	
	//1============================================================================================	
	
	
	function liveHandler(event){//#s5484-e5616
		
		var stop,maxLevel,related,match,handleObj,elem,j,i,l,data,close,namespace,ret,
		elems=[],
		selectors=[],
		events=jQuery._data(this,"events");		
		
		// Make sure we avoid non-left-click bubbling in Firefox (#3861) and
		// disabled elements in IE (#6911)
		if(event.liveFired===this||!events||!events.live||event.target.disabled||event.button&&event.type==="click"){
			
			return ;			
			
		}

		
		if(event.namespace){
			
			namespace=new RegExp("(^|\\.)"+event.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)");			
			
		}

		
		event.liveFired=this;		
		
		var live=events.live.slice(0);		
		
		for(j=0;j<live.length;j++){
			
			handleObj=live[j];			
			
			if(handleObj.origType.replace(rnamespaces,"")===event.type){
				
				selectors.push(handleObj.selector);				
				
				
			}else {
				
				live.splice(j--,1);				
				
			}
			
		}

		
		match=jQuery(event.target).closest(selectors,event.currentTarget);		
		
		for(i=0,l=match.length;i<l;i++){
			
			close=match[i];			
			
			for(j=0;j<live.length;j++){
				
				handleObj=live[j];				
				
				if(close.selector===handleObj.selector&&(!namespace||namespace.test(handleObj.namespace))&&!close.elem.disabled){
					
					elem=close.elem;					
					related=null;					
					
					// Those two events require additional checking
					if(handleObj.preType==="mouseenter"||handleObj.preType==="mouseleave"){
						
						event.type=handleObj.preType;						
						related=jQuery(event.relatedTarget).closest(handleObj.selector)[0];						
						
						// Make sure not to accidentally match a child element with
						// the same selector
						if(related&&jQuery.contains(elem,related)){
							
							related=elem;							
							
						}
						
					}

					
					if(!related||related!==elem){
						
						elems.push({
							elem:elem,handleObj:handleObj,level:close.level
						});						
						
					}
					
				}
				
			}
			
		}

		
		for(i=0,l=elems.length;i<l;i++){
			
			match=elems[i];			
			
			if(maxLevel&&match.level>maxLevel){
				
				break;				
				
			}

			
			event.currentTarget=match.elem;			
			event.data=match.handleObj.data;			
			event.handleObj=match.handleObj;			
			
			ret=match.handleObj.origHandler.apply(match.elem,arguments);			
			
			if(ret===false||event.isPropagationStopped()){
				
				maxLevel=match.level;				
				
				if(ret===false){
					
					stop=false;					
					
				}

				if(event.isImmediatePropagationStopped()){
					
					break;					
					
				}
				
			}
			
		}

		
		return stop;		
		
	}//#s5484-e5616
	
	
	//1============================================================================================	

	
	function liveConvert(type,selector){
		
		return (type&&type!=="*"?type+".":"")+selector.replace(rperiod,"`").replace(rspaces,"&");		
		
	}
	
	
	//1============================================================================================	


	/**
	 * 这里为jQuery增加多个非常有用的方法：
	 * (1)blur方法：为 "blur" 事件绑定一个处理函数，或者触发元素上的 "blur" 事件，在元素失去焦点时将触发blur事件。其实，这个函数是 .bind('blur', handler) 的快捷方式。
	 * (2)focus方法：为 "focus" 事件绑定一个处理函数，或者触发元素上的 "focus" 事件，在元素获得焦点时将触发focus事件。其实，这个函数是 .bind('focus', handler) 的快捷方式
	 * (3)focusin方法：将一个事件函数绑定到"focusin" 事件。其实，这个函数是 .bind('focusin', handler) 的快捷方式。
	 * (4)focusout方法：将一个事件函数绑定到"focusout" 事件。其实，这个方法是 .bind('focusout', handler) 的快捷方式。
	 * (5)load方法：为 "load" 事件绑定一个处理函数。其实，这个方法是 .bind('load', handler) 的快捷方式。注意：#s10798-e10901处也有一个叫.load()方法，后者用于远程加载HTML文件
	 * (6)resize方法：为 "resize" 事件绑定一个处理函数，或者触发元素上的 "resize" 事件。其实，这个函数是 .bind('resize', handler) 的快捷方式。
	 * (7)scroll方法：为 "scroll" 事件绑定一个处理函数，或者触发元素上的 "scroll" 事件。其实，这个函数是 .bind('scroll', handler) 的快捷方式。
	 * (8)unload方法：为 "unload" 事件绑定一个处理函数，或者触发元素上的 "unload" 事件。其实，这个函数是 .bind('unload', handler) 的快捷方式。
	 * (9)click方法：为 "click" 事件绑定一个处理函数，或者触发元素上的 "click" 事件。其实，这个函数是 .bind('click', handler) 的快捷方式。
	 * (10)dblclick方法：为 "dblclick" 事件绑定一个处理函数，或者触发元素上的 "dblclick" 事件，在元素被双击时候将触发 dblclick 事件。其实，这个函数是 .bind('dblclick', handler) 的快捷方式。
	 * (11)mousedown方法：为 "mousedown" 事件绑定一个处理函数，或者触发元素上的 "mousedown" 事件，当鼠标指针在元素上并按下鼠标键时，将触发mousedown事件。其实，这个函数是 .bind('mousedown', handler) 的快捷方式。
	 * (12)mouseup方法：为 "mouseup" 事件绑定一个处理函数，或者触发元素上的 "mouseup" 事件，当鼠标指针在元素内并且鼠标按键被释放时，将触发mouseup事件。其实，这个函数是 .bind('mouseup', handler) 的快捷方式。
	 * (13)mousemove方法：为 "mousemove" 事件绑定一个处理函数，或者触发元素上的 "mousemove" 事件，当鼠标指针在元素内移动时，将触发mousemove事件。其实，这个函数是 .bind('mousemove', handler) 的快捷方式。
	 * (14)mouseover方法：为 "mouseover" 事件绑定一个处理函数，或者触发元素上的 "mouseover" 事件，当鼠标指针进入元素内时，将触发mouseover事件。其实，这个函数是 .bind('mouseover', handler) 的快捷方式。
	 * (15)mouseout方法：为 "mouseout" 事件绑定一个处理函数，或者触发元素上的 "mouseout" 事件，当鼠标指针离开元素时，将触发mouseout事件。其实，这个函数是 .bind('mouseout', handler) 的快捷方式。
	 * (16)mouseenter方法：为 "mouseenter" 事件绑定一个处理函数，或者触发元素上的 "mouseenter" 事件，当鼠标指针进入的元素时，将触发mouseenter事件。其实，这个函数是 .bind('mouseenter', handler) 的快捷方式。
	 * (17)mouseleave方法：为 mouse leaves（鼠标离开） 事件绑定一个处理函数，或者触发元素上的 mouse leaves（鼠标离开） 事件。其实，这个函数是 .bind('mouseleave', handler) 的快捷方式。
	 * (18)change方法：为 "change" 事件绑定一个处理函数，或者触发元素上的 "change" 事件，当元素的值改变时，将触发change事件。其实，这个函数是 .bind('change', handler) 的快捷方式。
	 * (19)select方法：为 "select" 事件绑定一个处理函数，或者触发元素上的 "select" 事件，此事件只用在<input type="text"> 和<textarea>，当在元素中进行文本选择时，将触发select事件。其实，这个函数是 .bind('select', handler) 的快捷方式。
	 * (20)submit方法：为 "submit" 事件绑定一个处理函数，或者触发元素上的 "submit" 事件，只能用于<form>元素，当提交表单时，将触发submit事件。其实，这个函数是 .bind('submit', handler) 的快捷方式。
	 * (21)keydown方法：为 "keydown" 事件绑定一个处理函数，或者触发元素上的 "keydown" 事件，当用户在元素上并按下键盘上的键时，将触发keydown事件。其实，这个函数是 .bind('keydown', handler) 的快捷方式。
	 * (22)keypress方法：为 "keypress" 事件绑定一个处理函数，或者触发元素上的 "keypress" 事件，当用户在元素上并按下键盘上的键时，将触发keypress事件。其实，这个函数是 .bind('keypress', handler) 的快捷方式。
	 * (23)keyup方法：为 "keyup" 事件绑定一个处理函数，或者触发元素上的 "keyup" 事件，当用户在元素上释放按键时，将触发keyup事件。其实，这个函数是 .bind('keyup', handler) 的快捷方式。
	 * (24)error方法：绑定一个事件处理器到“错误”JavaScript事件上。其实，这个函数是 .bind('error', handler) 的快捷方式。
	 */
	jQuery.each(("blur focus focusin focusout load resize scroll unload click dblclick "+
	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave "+
	"change select submit keydown keypress keyup error").split(" "),function (i,name){//#s5939-e5965
		
		
		// Handle event binding
		jQuery.fn[name]=function (data,fn){
			
			if(fn==null){
				
				fn=data;				
				data=null;				
				
			}

			
			return arguments.length>0?
			this.bind(name,data,fn):
			this.trigger(name);			
			
		};		
		
		if(jQuery.attrFn){
			
			jQuery.attrFn[name]=true;			
			
		}
		
	});	//#s5939-e5965
	
	
	//1============================================================================================	
	
	
	/*
	 * ! Sizzle CSS Selector Engine Copyright 2011, The Dojo Foundation Released
	 * under the MIT, BSD, and GPL Licenses. More information: http://sizzlejs.com/
	 */
	(function (){//#s5670-e7801
		
		
		var chunker=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
		done=0,
		toString =Object.prototype.toString ,
		hasDuplicate=false,
		baseHasDuplicate=true,
		rBackslash=/\\/g,
		rNonWord=/\W/;		
		
		// Here we check if the JavaScript engine is using some sort of
		// optimization where it does not always call our comparision
		// function. If that is the case, discard the hasDuplicate value.
		// Thus far that includes Google Chrome.
		[0,0].sort(function (){
			
			baseHasDuplicate=false;			
			return 0;			
			
		});		
		
		var Sizzle=function (selector,context,results,seed){
			
			results=results||[];			
			context=context||document;			
			
			var origContext=context;			
			
			if(context.nodeType!==1&&context.nodeType!==9){
				
				return [];				
				
			}

			
			if(!selector||typeof selector!=="string"){
				
				return results;				
				
			}

			
			var m,set,checkSet,extra,ret,cur,pop,i,
			prune=true,
			contextXML=Sizzle.isXML(context),
			parts=[],
			soFar=selector;			
			
			// Reset the position of the chunker regexp (start from head)
			do{
				
				chunker.exec("");				
				m=chunker.exec(soFar);				
				
				if(m){
					
					soFar=m[3];					
					
					parts.push(m[1]);					
					
					if(m[2]){
						
						extra=m[3];						
						break;						
						
					}
					
				}
				
			}while(m);			
			
			if(parts.length>1&&origPOS.exec(selector)){
				
				
				if(parts.length===2&&Expr.relative[parts[0]]){
					
					set=posProcess(parts[0]+parts[1],context);					
					
					
				}else {
					
					set=Expr.relative[parts[0]]?
					[context]:
					Sizzle(parts.shift(),context);					
					
					while(parts.length){
						
						selector=parts.shift();						
						
						if(Expr.relative[selector]){
							
							selector+=parts.shift();							
							
						}

						
						set=posProcess(selector,set);						
						
					}
					
				}
				
				
			}else {
				
				// Take a shortcut and set the context if the root selector is an ID
				// (but not if it'll be faster if the inner selector is an ID)
				if(!seed&&parts.length>1&&context.nodeType===9&&!contextXML&&
				Expr.match.ID.test(parts[0])&&!Expr.match.ID.test(parts[parts.length-1])){
					
					
					ret=Sizzle.find(parts.shift(),context,contextXML);					
					context=ret.expr?
					Sizzle.filter(ret.expr,ret.set)[0]:
					ret.set[0];					
					
				}

				
				if(context){
					
					ret=seed?
					{
						expr:parts.pop(),set:makeArray(seed)
					}
:
					Sizzle.find(parts.pop(),parts.length===1&&(parts[0]==="~"||parts[0]==="+")&&context.parentNode?context.parentNode:context,contextXML);					
					
					set=ret.expr?
					Sizzle.filter(ret.expr,ret.set):
					ret.set;					
					
					if(parts.length>0){
						
						checkSet=makeArray(set);						
						
						
					}else {
						
						prune=false;						
						
					}
					
					while(parts.length){
						
						cur=parts.pop();						
						pop=cur;						
						
						if(!Expr.relative[cur]){
							
							cur="";							
							
						}else {
							
							pop=parts.pop();							
							
						}

						
						if(pop==null){
							
							pop=context;							
							
						}

						
						Expr.relative[cur](checkSet,pop,contextXML);						
						
					}
					
					
				}else {
					
					checkSet=parts=[];					
					
				}
				
			}

			
			if(!checkSet){
				
				checkSet=set;				
				
			}

			
			if(!checkSet){
				
				Sizzle.error(cur||selector);				
				
			}

			
			if(toString .call(checkSet)==="[object Array]"){
				
				if(!prune){
					
					results.push.apply(results,checkSet);					
					
					
				}else if(context&&context.nodeType===1){
					
					for(i=0;checkSet[i]!=null;i++){
						
						if(checkSet[i]&&(checkSet[i]===true||checkSet[i].nodeType===1&&Sizzle.contains(context,checkSet[i]))){
							
							results.push(set[i]);							
							
						}
						
					}
					
					
				}else {
					
					for(i=0;checkSet[i]!=null;i++){
						
						if(checkSet[i]&&checkSet[i].nodeType===1){
							
							results.push(set[i]);							
							
						}
						
					}
					
				}
				
				
			}else {
				
				makeArray(checkSet,results);				
				
			}

			
			if(extra){
				
				Sizzle(extra,origContext,results,seed);				
				Sizzle.uniqueSort(results);				
				
			}

			
			return results;			
			
		};		
		
		Sizzle.uniqueSort=function (results){
			
			if(sortOrder){
				
				hasDuplicate=baseHasDuplicate;				
				results.sort(sortOrder);				
				
				if(hasDuplicate){
					
					for(var i=1;i<results.length;i++){
						
						if(results[i]===results[i-1]){
							
							results.splice(i--,1);							
							
						}
						
					}
					
				}
				
			}

			
			return results;			
			
		};		
		
		Sizzle.matches=function (expr,set){
			
			return Sizzle(expr,null,null,set);			
			
		};		
		
		Sizzle.matchesSelector=function (node,expr){
			
			return Sizzle(expr,null,null,[node]).length>0;			
			
		};		
		
		Sizzle.find=function (expr,context,isXML){
			
			var set;			
			
			if(!expr){
				
				return [];				
				
			}

			
			for(var i=0,l=Expr.order.length;i<l;i++){
				
				var match,
				type=Expr.order[i];				
				
				if((match=Expr.leftMatch[type].exec(expr))){
					
					var left=match[1];					
					match.splice(1,1);					
					
					if(left.substr(left.length-1)!=="\\"){
						
						match[1]=(match[1]||"").replace(rBackslash,"");						
						set=Expr.find[type](match,context,isXML);						
						
						if(set!=null){
							
							expr=expr.replace(Expr.match[type],"");							
							break;							
							
						}
						
					}
					
				}
				
			}

			
			if(!set){
				
				set=typeof context.getElementsByTagName!=="undefined"?
				context.getElementsByTagName("*"):
				[];				
				
			}

			
			return {
				set:set,expr:expr
			};			
			
		};		
		
		Sizzle.filter=function (expr,set,inplace,not){
			
			var match,anyFound,
			old=expr,
			result=[],
			curLoop=set,
			isXMLFilter=set&&set[0]&&Sizzle.isXML(set[0]);			
			
			while(expr&&set.length){
				
				for(var type in Expr.filter){
					
					if((match=Expr.leftMatch[type].exec(expr))!=null&&match[2]){
						
						var found,item,
						filter=Expr.filter[type],
						left=match[1];						
						
						anyFound=false;						
						
						match.splice(1,1);						
						
						if(left.substr(left.length-1)==="\\"){
							
							continue;							
							
						}

						
						if(curLoop===result){
							
							result=[];							
							
						}

						
						if(Expr.preFilter[type]){
							
							match=Expr.preFilter[type](match,curLoop,inplace,result,not,isXMLFilter);							
							
							if(!match){
								
								anyFound=found=true;								
								
								
							}else if(match===true){
								
								continue;								
								
							}
							
						}

						
						if(match){
							
							for(var i=0;(item=curLoop[i])!=null;i++){
								
								if(item){
									
									found=filter(item,match,i,curLoop);									
									var pass=not^!!found;									
									
									if(inplace&&found!=null){
										
										if(pass){
											
											anyFound=true;											
											
											
										}else {
											
											curLoop[i]=false;											
											
										}
										
										
									}else if(pass){
										
										result.push(item);										
										anyFound=true;										
										
									}
									
								}
								
							}
							
						}

						
						if(found!==undefined){
							
							if(!inplace){
								
								curLoop=result;								
								
							}

							
							expr=expr.replace(Expr.match[type],"");							
							
							if(!anyFound){
								
								return [];								
								
							}

							
							break;							
							
						}
						
					}
					
				}

				
				// Improper expression
				if(expr===old){
					
					if(anyFound==null){
						
						Sizzle.error(expr);						
						
						
					}else {
						
						break;						
						
					}
					
				}

				
				old=expr;				
				
			}

			
			return curLoop;			
			
		};		
		
		Sizzle.error=function (msg){
			
			throw"Syntax error, unrecognized expression: "+msg;			
			
		};		
		
		var Expr=Sizzle.selectors={
			
			order:["ID","NAME","TAG"],
			
			match:{
				
				ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
				CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
				NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
				ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,
				TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
				CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,
				POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
				PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
				
			},
			
			leftMatch:{
				
			},
			
			attrMap:{
				
				"class":"className",
				"for":"htmlFor"
				
			},
			
			attrHandle:{
				
				href:function (elem){
					
					return elem.getAttribute("href");					
					
				},
				type:function (elem){
					
					return elem.getAttribute("type");					
					
				}
				
			},
			
			relative:{
				
				"+":function (checkSet,part){
					
					var isPartStr=typeof part==="string",
					isTag=isPartStr&&!rNonWord.test(part),
					isPartStrNotTag=isPartStr&&!isTag;					
					
					if(isTag){
						
						part=part.toLowerCase();						
						
					}

					
					for(var i=0,l=checkSet.length,elem;i<l;i++){
						
						if((elem=checkSet[i])){
							
							while((elem=elem.previousSibling)&&elem.nodeType!==1){
								
							}

							
							checkSet[i]=isPartStrNotTag||elem&&elem.nodeName.toLowerCase()===part?
							elem||false:
							elem===part;							
							
						}
						
					}

					
					if(isPartStrNotTag){
						
						Sizzle.filter(part,checkSet,true);						
						
					}
					
				},
				
				">":function (checkSet,part){
					
					var elem,
					isPartStr=typeof part==="string",
					i=0,
					l=checkSet.length;					
					
					if(isPartStr&&!rNonWord.test(part)){
						
						part=part.toLowerCase();						
						
						for(;i<l;i++){
							
							elem=checkSet[i];							
							
							if(elem){
								
								var parent=elem.parentNode;								
								checkSet[i]=parent.nodeName.toLowerCase()===part?parent:false;								
								
							}
							
						}
						
						
					}else {
						
						for(;i<l;i++){
							
							elem=checkSet[i];							
							
							if(elem){
								
								checkSet[i]=isPartStr?
								elem.parentNode:
								elem.parentNode===part;								
								
							}
							
						}

						
						if(isPartStr){
							
							Sizzle.filter(part,checkSet,true);							
							
						}
						
					}
					
				},
				
				"":function (checkSet,part,isXML){
					
					var nodeCheck,
					doneName=done++,
					checkFn=dirCheck;					
					
					if(typeof part==="string"&&!rNonWord.test(part)){
						
						part=part.toLowerCase();						
						nodeCheck=part;						
						checkFn=dirNodeCheck;						
						
					}

					
					checkFn("parentNode",part,doneName,checkSet,nodeCheck,isXML);					
					
				},
				
				"~":function (checkSet,part,isXML){
					
					var nodeCheck,
					doneName=done++,
					checkFn=dirCheck;					
					
					if(typeof part==="string"&&!rNonWord.test(part)){
						
						part=part.toLowerCase();						
						nodeCheck=part;						
						checkFn=dirNodeCheck;						
						
					}

					
					checkFn("previousSibling",part,doneName,checkSet,nodeCheck,isXML);					
					
				}
				
			},
			
			find:{
				
				ID:function (match,context,isXML){
					
					if(typeof context.getElementById!=="undefined"&&!isXML){
						
						var m=context.getElementById(match[1]);						
						// Check parentNode to catch when Blackberry 4.6 returns
						// nodes that are no longer in the document #6963
						return m&&m.parentNode?[m]:[];						
						
					}
					
				},
				
				NAME:function (match,context){
					
					if(typeof context.getElementsByName!=="undefined"){
						
						var ret=[],
						results=context.getElementsByName(match[1]);						
						
						for(var i=0,l=results.length;i<l;i++){
							
							if(results[i].getAttribute("name")===match[1]){
								
								ret.push(results[i]);								
								
							}
							
						}

						
						return ret.length===0?null:ret;						
						
					}
					
				},
				
				TAG:function (match,context){
					
					if(typeof context.getElementsByTagName!=="undefined"){
						
						return context.getElementsByTagName(match[1]);						
						
					}
					
				}
				
			},
			preFilter:{
				
				CLASS:function (match,curLoop,inplace,result,not,isXML){
					
					match=" "+match[1].replace(rBackslash,"")+" ";					
					
					if(isXML){
						
						return match;						
						
					}

					
					for(var i=0,elem;(elem=curLoop[i])!=null;i++){
						
						if(elem){
							
							if(not^(elem.className&&(" "+elem.className+" ").replace(/[\t\n\r]/g," ").indexOf(match)>=0)){
								
								if(!inplace){
									
									result.push(elem);									
									
								}
								
								
							}else if(inplace){
								
								curLoop[i]=false;								
								
							}
							
						}
						
					}

					
					return false;					
					
				},
				
				ID:function (match){
					
					return match[1].replace(rBackslash,"");					
					
				},
				
				TAG:function (match,curLoop){
					
					return match[1].replace(rBackslash,"").toLowerCase();					
					
				},
				
				CHILD:function (match){
					
					if(match[1]==="nth"){
						
						if(!match[2]){
							
							Sizzle.error(match[0]);							
							
						}

						
						match[2]=match[2].replace(/^\+|\s/g,'');						
						
						// parse equations like 'even', 'odd', '5', '2n', '3n+2',
						// '4n-1', '-n+6'
						var test=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(
						match[2]==="even"&&"2n"||match[2]==="odd"&&"2n+1"||
						!/\D/.test(match[2])&&"0n+"+match[2]||match[2]);						
						
						// calculate the numbers (first)n+(last) including if they are
						// negative
						match[2]=(test[1]+(test[2]||1))-0;						
						match[3]=test[3]-0;						
						
					}
					else if(match[2]){
						
						Sizzle.error(match[0]);						
						
					}

					
					// TODO: Move to normal caching system
					match[0]=done++;					
					
					return match;					
					
				},
				
				ATTR:function (match,curLoop,inplace,result,not,isXML){
					
					var name=match[1]=match[1].replace(rBackslash,"");					
					
					if(!isXML&&Expr.attrMap[name]){
						
						match[1]=Expr.attrMap[name];						
						
					}

					
					// Handle if an un-quoted value was used
					match[4]=(match[4]||match[5]||"").replace(rBackslash,"");					
					
					if(match[2]==="~="){
						
						match[4]=" "+match[4]+" ";						
						
					}

					
					return match;					
					
				},
				
				PSEUDO:function (match,curLoop,inplace,result,not){
					
					if(match[1]==="not"){
						
						// If we're dealing with a complex expression, or a simple one
						if((chunker.exec(match[3])||"").length>1||/^\w/.test(match[3])){
							
							match[3]=Sizzle(match[3],null,null,curLoop);							
							
							
						}else {
							
							var ret=Sizzle.filter(match[3],curLoop,inplace,true^not);							
							
							if(!inplace){
								
								result.push.apply(result,ret);								
								
							}

							
							return false;							
							
						}
						
						
					}else if(Expr.match.POS.test(match[0])||Expr.match.CHILD.test(match[0])){
						
						return true;						
						
					}

					
					return match;					
					
				},
				
				POS:function (match){
					
					match.unshift(true);					
					
					return match;					
					
				}
				
			},
			
			filters:{
				
				enabled:function (elem){
					
					return elem.disabled===false&&elem.type!=="hidden";					
					
				},
				
				disabled:function (elem){
					
					return elem.disabled===true;					
					
				},
				
				checked:function (elem){
					
					return elem.checked===true;					
					
				},
				
				selected:function (elem){
					
					// Accessing this property makes selected-by-default
					// options in Safari work properly
					if(elem.parentNode){
						
						elem.parentNode.selectedIndex;						
						
					}

					
					return elem.selected===true;					
					
				},
				
				parent:function (elem){
					
					return !!elem.firstChild;					
					
				},
				
				empty:function (elem){
					
					return !elem.firstChild;					
					
				},
				
				has:function (elem,i,match){
					
					return !!Sizzle(match[3],elem).length;					
					
				},
				
				header:function (elem){
					
					return (/h\d/i).test(elem.nodeName);					
					
				},
				
				text:function (elem){
					
					var attr=elem.getAttribute("type"),type=elem.type;					
					// IE6 and 7 will map elem.type to 'text' for new HTML5 types
					// (search, etc)
					// use getAttribute instead to test this case
					return elem.nodeName.toLowerCase()==="input"&&"text"===type&&(attr===type||attr===null);					
					
				},
				
				radio:function (elem){
					
					return elem.nodeName.toLowerCase()==="input"&&"radio"===elem.type;					
					
				},
				
				checkbox:function (elem){
					
					return elem.nodeName.toLowerCase()==="input"&&"checkbox"===elem.type;					
					
				},
				
				file:function (elem){
					
					return elem.nodeName.toLowerCase()==="input"&&"file"===elem.type;					
					
				},
				
				password:function (elem){
					
					return elem.nodeName.toLowerCase()==="input"&&"password"===elem.type;					
					
				},
				
				submit:function (elem){
					
					var name=elem.nodeName.toLowerCase();					
					return (name==="input"||name==="button")&&"submit"===elem.type;					
					
				},
				
				image:function (elem){
					
					return elem.nodeName.toLowerCase()==="input"&&"image"===elem.type;					
					
				},
				
				reset:function (elem){
					
					var name=elem.nodeName.toLowerCase();					
					return (name==="input"||name==="button")&&"reset"===elem.type;					
					
				},
				
				button:function (elem){
					
					var name=elem.nodeName.toLowerCase();					
					return name==="input"&&"button"===elem.type||name==="button";					
					
				},
				
				input:function (elem){
					
					return (/input|select|textarea|button/i).test(elem.nodeName);					
					
				},
				
				focus:function (elem){
					
					return elem===elem.ownerDocument.activeElement;					
					
				}
				
			},
			setFilters:{
				
				first:function (elem,i){
					
					return i===0;					
					
				},
				
				last:function (elem,i,match,array){
					
					return i===array.length-1;					
					
				},
				
				even:function (elem,i){
					
					return i%2===0;					
					
				},
				
				odd:function (elem,i){
					
					return i%2===1;					
					
				},
				
				lt:function (elem,i,match){
					
					return i<match[3]-0;					
					
				},
				
				gt:function (elem,i,match){
					
					return i>match[3]-0;					
					
				},
				
				nth:function (elem,i,match){
					
					return match[3]-0===i;					
					
				},
				
				eq:function (elem,i,match){
					
					return match[3]-0===i;					
					
				}
				
			},
			filter:{
				
				PSEUDO:function (elem,match,i,array){
					
					var name=match[1],
					filter=Expr.filters[name];					
					
					if(filter){
						
						return filter(elem,i,match,array);						
						
						
					}else if(name==="contains"){
						
						return (elem.textContent||elem.innerText||Sizzle.getText([elem])||"").indexOf(match[3])>=0;						
						
						
					}else if(name==="not"){
						
						var not=match[3];						
						
						for(var j=0,l=not.length;j<l;j++){
							
							if(not[j]===elem){
								
								return false;								
								
							}
							
						}

						
						return true;						
						
						
					}else {
						
						Sizzle.error(name);						
						
					}
					
				},
				
				CHILD:function (elem,match){
					
					var type=match[1],
					node=elem;					
					
					switch(type){
						
						case "only":
						case "first":
						while((node=node.previousSibling)){
							
							if(node.nodeType===1){
								
								return false;
								
								
							}
							
						}

						
						if(type==="first"){
							
							return true;
							
							
						}

						
						node=elem;						
						
						case "last":
						while((node=node.nextSibling)){
							
							if(node.nodeType===1){
								
								return false;
								
								
							}
							
						}

						
						return true;						
						
						case "nth":
						var first=match[2],
						last=match[3];						
						
						if(first===1&&last===0){
							
							return true;							
							
						}

						
						var doneName=match[0],
						parent=elem.parentNode;						
						
						if(parent&&(parent.sizcache!==doneName||!elem.nodeIndex)){
							
							var count=0;							
							
							for(node=parent.firstChild;node;node=node.nextSibling){
								
								if(node.nodeType===1){
									
									node.nodeIndex=++count;									
									
								}
								
							}

							
							parent.sizcache=doneName;							
							
						}

						
						var diff=elem.nodeIndex-last;						
						
						if(first===0){
							
							return diff===0;							
							
							
						}else {
							
							return (diff%first===0&&diff/first>=0);							
							
						}
						
					}
					
				},
				
				ID:function (elem,match){
					
					return elem.nodeType===1&&elem.getAttribute("id")===match;					
					
				},
				
				TAG:function (elem,match){
					
					return (match==="*"&&elem.nodeType===1)||elem.nodeName.toLowerCase()===match;					
					
				},
				
				CLASS:function (elem,match){
					
					return (" "+(elem.className||elem.getAttribute("class"))+" ")
					.indexOf(match)>-1;					
					
				},
				
				ATTR:function (elem,match){
					
					var name=match[1],
					result=Expr.attrHandle[name]?
					Expr.attrHandle[name](elem):
					elem[name]!=null?
					elem[name]:
					elem.getAttribute(name),
					value=result+"",
					type=match[2],
					check=match[4];					
					
					return result==null?
					type==="!=":
					type==="="?
					value===check:
					type==="*="?
					value.indexOf(check)>=0:
					type==="~="?
					(" "+value+" ").indexOf(check)>=0:
					!check?
					value&&result!==false:
					type==="!="?
					value!==check:
					type==="^="?
					value.indexOf(check)===0:
					type==="$="?
					value.substr(value.length-check.length)===check:
					type==="|="?
					value===check||value.substr(0,check.length+1)===check+"-":
					false;					
					
				},
				
				POS:function (elem,match,i,array){
					
					var name=match[2],
					filter=Expr.setFilters[name];					
					
					if(filter){
						
						return filter(elem,i,match,array);						
						
					}
					
				}
				
			}
			
		};		
		
		var origPOS=Expr.match.POS,
		fescape=function (all,num){
			
			return "\\"+(num-0+1);			
			
		};		
		
		for(var type in Expr.match){
			
			Expr.match[type]=new RegExp(Expr.match[type].source+(/(?![^\[]*\])(?![^\(]*\))/.source));			
			Expr.leftMatch[type]=new RegExp(/(^(?:.|\r|\n)*?)/.source+Expr.match[type].source.replace(/\\(\d+)/g,fescape));			
			
		}

		
		var makeArray=function (array,results){
			
			array=Array.prototype.slice.call(array,0);			
			
			if(results){
				
				results.push.apply(results,array);				
				return results;				
				
			}

			
			return array;			
			
		};		
		
		// Perform a simple check to determine if the browser is capable of
		// converting a NodeList to an array using builtin methods.
		// Also verifies that the returned array holds DOM nodes
		// (which is not the case in the Blackberry browser)
		try{
			
			Array.prototype.slice.call(document.documentElement.childNodes,0)[0].nodeType;			
			
			// Provide a fallback method if it does not work
			
		}catch(e){
			
			makeArray=function (array,results){
				
				var i=0,
				ret=results||[];				
				
				if(toString .call(array)==="[object Array]"){
					
					Array.prototype.push.apply(ret,array);					
					
					
				}else {
					
					if(typeof array.length==="number"){
						
						for(var l=array.length;i<l;i++){
							
							ret.push(array[i]);							
							
						}
						
						
					}else {
						
						for(;array[i];i++){
							
							ret.push(array[i]);							
							
						}
						
					}
					
				}

				
				return ret;				
				
			};			
			
		}

		
		var sortOrder,siblingCheck;		
		
		if(document.documentElement.compareDocumentPosition){
			
			sortOrder=function (a,b){
				
				if(a===b){
					
					hasDuplicate=true;					
					return 0;					
					
				}

				
				if(!a.compareDocumentPosition||!b.compareDocumentPosition){
					
					return a.compareDocumentPosition?-1:1;					
					
				}

				
				return a.compareDocumentPosition(b)&4?-1:1;				
				
			};			
			
			
		}else {
			
			sortOrder=function (a,b){
				
				// The nodes are identical, we can exit early
				if(a===b){
					
					hasDuplicate=true;					
					return 0;					
					
					// Fallback to using sourceIndex (in IE) if it's available on both nodes
					
				}else if(a.sourceIndex&&b.sourceIndex){
					
					return a.sourceIndex-b.sourceIndex;					
					
				}

				
				var al,bl,
				ap=[],
				bp=[],
				aup=a.parentNode,
				bup=b.parentNode,
				cur=aup;				
				
				// If the nodes are siblings (or identical) we can do a quick check
				if(aup===bup){
					
					return siblingCheck(a,b);					
					
					// If no parents were found then the nodes are disconnected
					
				}else if(!aup){
					
					return -1;					
					
					
				}else if(!bup){
					
					return 1;					
					
				}

				
				// Otherwise they're somewhere else in the tree so we need
				// to build up a full list of the parentNodes for comparison
				while(cur){
					
					ap.unshift(cur);					
					cur=cur.parentNode;					
					
				}

				
				cur=bup;				
				
				while(cur){
					
					bp.unshift(cur);					
					cur=cur.parentNode;					
					
				}

				
				al=ap.length;				
				bl=bp.length;				
				
				// Start walking down the tree looking for a discrepancy
				for(var i=0;i<al&&i<bl;i++){
					
					if(ap[i]!==bp[i]){
						
						return siblingCheck(ap[i],bp[i]);						
						
					}
					
				}

				
				// We ended someplace up the tree so do a sibling check
				return i===al?
				siblingCheck(a,bp[i],-1):
				siblingCheck(ap[i],b,1);				
				
			};			
			
			siblingCheck=function (a,b,ret){
				
				if(a===b){
					
					return ret;					
					
				}

				
				var cur=a.nextSibling;				
				
				while(cur){
					
					if(cur===b){
						
						return -1;						
						
					}

					
					cur=cur.nextSibling;					
					
				}

				
				return 1;				
				
			};			
			
		}

		
		// Utility function for retreiving the text value of an array of DOM nodes
		Sizzle.getText=function (elems){
			
			var ret="",elem;			
			
			for(var i=0;elems[i];i++){
				
				elem=elems[i];				
				
				// Get the text from text nodes and CDATA nodes
				if(elem.nodeType===3||elem.nodeType===4){
					
					ret+=elem.nodeValue;					
					
					// Traverse everything else, except comment nodes
					
				}else if(elem.nodeType!==8){
					
					ret+=Sizzle.getText(elem.childNodes);					
					
				}
				
			}

			
			return ret;			
			
		};		
		
		// Check to see if the browser returns elements by name when
		// querying by getElementById (and provide a workaround)
		(function (){
			
			// We're going to inject a fake input element with a specified name
			var form=document.createElement("div"),
			id="script"+(new Date()).getTime(),
			root=document.documentElement;			
			
			form.innerHTML="<a name='"+id+"'/>";			
			
			// Inject it into the root element, check its status, and remove it quickly
			root.insertBefore(form,root.firstChild);			
			
			// The workaround has to do additional checks after a getElementById
			// Which slows things down for other browsers (hence the branching)
			if(document.getElementById(id)){
				
				Expr.find.ID=function (match,context,isXML){
					
					if(typeof context.getElementById!=="undefined"&&!isXML){
						
						var m=context.getElementById(match[1]);						
						
						return m?
						m.id===match[1]||typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id").nodeValue===match[1]?
						[m]:
						undefined:
						[];						
						
					}
					
				};				
				
				Expr.filter.ID=function (elem,match){
					
					var node=typeof elem.getAttributeNode!=="undefined"&&elem.getAttributeNode("id");					
					
					return elem.nodeType===1&&node&&node.nodeValue===match;					
					
				};				
				
			}

			
			root.removeChild(form);			
			
			// release memory in IE
			root=form=null;			
			
		})();		
		
		(function (){
			
			// Check to see if the browser returns only elements
			// when doing getElementsByTagName("*")
			
			// Create a fake element
			var div=document.createElement("div");			
			div.appendChild(document.createComment(""));			
			
			// Make sure no comments are found
			if(div.getElementsByTagName("*").length>0){
				
				Expr.find.TAG=function (match,context){
					
					var results=context.getElementsByTagName(match[1]);					
					
					// Filter out possible comments
					if(match[1]==="*"){
						
						var tmp=[];						
						
						for(var i=0;results[i];i++){
							
							if(results[i].nodeType===1){
								
								tmp.push(results[i]);								
								
							}
							
						}

						
						results=tmp;						
						
					}

					
					return results;					
					
				};				
				
			}

			
			// Check to see if an attribute returns normalized href attributes
			div.innerHTML="<a href='#'></a>";			
			
			if(div.firstChild&&typeof div.firstChild.getAttribute!=="undefined"&&
			div.firstChild.getAttribute("href")!=="#"){
				
				
				Expr.attrHandle.href=function (elem){
					
					return elem.getAttribute("href",2);					
					
				};				
				
			}

			
			// release memory in IE
			div=null;			
			
		})();		
		
		if(document.querySelectorAll){
			
			(function (){
				
				var oldSizzle=Sizzle,
				div=document.createElement("div"),
				id="__sizzle__";				
				
				div.innerHTML="<p class='TEST'></p>";				
				
				// Safari can't handle uppercase or unicode characters when
				// in quirks mode.
				if(div.querySelectorAll&&div.querySelectorAll(".TEST").length===0){
					
					return ;					
					
				}

				
				Sizzle=function (query,context,extra,seed){
					
					context=context||document;					
					
					// Only use querySelectorAll on non-XML documents
					// (ID selectors don't work in non-HTML documents)
					if(!seed&&!Sizzle.isXML(context)){
						
						// See if we find a selector to speed up
						var match=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(query);						
						
						if(match&&(context.nodeType===1||context.nodeType===9)){
							
							// Speed-up: Sizzle("TAG")
							if(match[1]){
								
								return makeArray(context.getElementsByTagName(query),extra);								
								
								// Speed-up: Sizzle(".CLASS")
								
							}else if(match[2]&&Expr.find.CLASS&&context.getElementsByClassName){
								
								return makeArray(context.getElementsByClassName(match[2]),extra);								
								
							}
							
						}

						
						if(context.nodeType===9){
							
							// Speed-up: Sizzle("body")
							// The body element only exists once, optimize finding it
							if(query==="body"&&context.body){
								
								return makeArray([context.body],extra);								
								
								// Speed-up: Sizzle("#ID")
								
							}else if(match&&match[3]){
								
								var elem=context.getElementById(match[3]);								
								
								// Check parentNode to catch when Blackberry 4.6 returns
								// nodes that are no longer in the document #6963
								if(elem&&elem.parentNode){
									
									// Handle the case where IE and Opera return items
									// by name instead of ID
									if(elem.id===match[3]){
										
										return makeArray([elem],extra);										
										
									}
									
									
								}else {
									
									return makeArray([],extra);									
									
								}
								
							}

							
							try{
								
								return makeArray(context.querySelectorAll(query),extra);								
								
							}catch(qsaError){
								
							}

							
							// qSA works strangely on Element-rooted queries
							// We can work around this by specifying an extra ID on the root
							// and working up from there (Thanks to Andrew Dupont for the
							// technique)
							// IE 8 doesn't work on object elements
							
						}else if(context.nodeType===1&&context.nodeName.toLowerCase()!=="object"){
							
							var oldContext=context,
							old=context.getAttribute("id"),
							nid=old||id,
							hasParent=context.parentNode,
							relativeHierarchySelector=/^\s*[+~]/.test(query);							
							
							if(!old){
								
								context.setAttribute("id",nid);								
								
							}else {
								
								nid=nid.replace(/'/g, "\\$&" );
								
							}

							if(relativeHierarchySelector&&hasParent){
								
								context=context.parentNode;								
								
							}

							
							try{
								
								if(!relativeHierarchySelector||hasParent){
									
									return makeArray(context.querySelectorAll("[id='"+nid+"'] "+query),extra);									
									
								}
								
								
							}catch(pseudoError){
								
								
							}
finally{
								
								if(!old){
									
									oldContext.removeAttribute("id");									
									
								}
								
							}
							
						}
						
					}

					
					return oldSizzle(query,context,extra,seed);					
					
				};				
				
				for(var prop in oldSizzle){
					
					Sizzle[prop]=oldSizzle[prop];					
					
				}

				
				// release memory in IE
				div=null;				
				
			})();			
			
		}

		
		(function (){
			
			var html=document.documentElement,
			matches=html.matchesSelector||html.mozMatchesSelector||html.webkitMatchesSelector||html.msMatchesSelector;			
			
			if(matches){
				
				// Check to see if it's possible to do matchesSelector
				// on a disconnected node (IE 9 fails this)
				var disconnectedMatch=!matches.call(document.createElement("div"),"div"),
				pseudoWorks=false;				
				
				try{
					
					// This should fail with an exception
					// Gecko does not error, returns false instead
					matches.call(document.documentElement,"[test!='']:sizzle");					
					
					
				}catch(pseudoError){
					
					pseudoWorks=true;					
					
				}

				
				Sizzle.matchesSelector=function (node,expr){
					
					// Make sure that attribute selectors are quoted
					expr=expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
					
					if(!Sizzle.isXML(node)){
						
						try{
							
							if(pseudoWorks||!Expr.match.PSEUDO.test(expr)&&!/!=/.test(expr)){
								
								var ret=matches.call(node,expr);								
								
								// IE 9's matchesSelector returns false on disconnected
								// nodes
								if(ret||!disconnectedMatch||
								// As well, disconnected nodes are said to be in
								// a document
								// fragment in IE 9, so check for that
								node.document&&node.document.nodeType!==11){
									
									return ret;									
									
								}
								
							}
							
						}catch(e){
							
						}
						
					}

					
					return Sizzle(expr,null,null,[node]).length>0;					
					
				};				
				
			}
			
		})();		
		
		(function (){
			
			var div=document.createElement("div");			
			
			div.innerHTML="<div class='test e'></div><div class='test'></div>";			
			
			// Opera can't find a second classname (in 9.6)
			// Also, make sure that getElementsByClassName actually exists
			if(!div.getElementsByClassName||div.getElementsByClassName("e").length===0){
				
				return ;				
				
			}

			
			// Safari caches class attributes, doesn't catch changes (in 3.2)
			div.lastChild.className="e";			
			
			if(div.getElementsByClassName("e").length===1){
				
				return ;				
				
			}

			
			Expr.order.splice(1,0,"CLASS");			
			Expr.find.CLASS=function (match,context,isXML){
				
				if(typeof context.getElementsByClassName!=="undefined"&&!isXML){
					
					return context.getElementsByClassName(match[1]);					
					
				}
				
			};			
			
			// release memory in IE
			div=null;			
			
		})();		
		
		function dirNodeCheck(dir,cur,doneName,checkSet,nodeCheck,isXML){
			
			for(var i=0,l=checkSet.length;i<l;i++){
				
				var elem=checkSet[i];				
				
				if(elem){
					
					var match=false;					
					
					elem=elem[dir];					
					
					while(elem){
						
						if(elem.sizcache===doneName){
							
							match=checkSet[elem.sizset];							
							break;							
							
						}

						
						if(elem.nodeType===1&&!isXML){
							
							elem.sizcache=doneName;							
							elem.sizset=i;							
							
						}

						
						if(elem.nodeName.toLowerCase()===cur){
							
							match=elem;							
							break;							
							
						}

						
						elem=elem[dir];						
						
					}

					
					checkSet[i]=match;					
					
				}
				
			}
			
		}

		
		function dirCheck(dir,cur,doneName,checkSet,nodeCheck,isXML){
			
			for(var i=0,l=checkSet.length;i<l;i++){
				
				var elem=checkSet[i];				
				
				if(elem){
					
					var match=false;					
					
					elem=elem[dir];					
					
					while(elem){
						
						if(elem.sizcache===doneName){
							
							match=checkSet[elem.sizset];							
							break;							
							
						}

						
						if(elem.nodeType===1){
							
							if(!isXML){
								
								elem.sizcache=doneName;								
								elem.sizset=i;								
								
							}

							
							if(typeof cur!=="string"){
								
								if(elem===cur){
									
									match=true;									
									break;									
									
								}
								
								
							}else if(Sizzle.filter(cur,[elem]).length>0){
								
								match=elem;								
								break;								
								
							}
							
						}

						
						elem=elem[dir];						
						
					}

					
					checkSet[i]=match;					
					
				}
				
			}
			
		}

		
		if(document.documentElement.contains){
			
			Sizzle.contains=function (a,b){
				
				return a!==b&&(a.contains?a.contains(b):true);				
				
			};			
			
			
		}else if(document.documentElement.compareDocumentPosition){
			
			Sizzle.contains=function (a,b){
				
				return !!(a.compareDocumentPosition(b)&16);				
				
			};			
			
			
		}else {
			
			Sizzle.contains=function (){
				
				return false;				
				
			};			
			
		}

		
		Sizzle.isXML=function (elem){
			
			// documentElement is verified for cases where it doesn't yet exist
			// (such as loading iframes in IE - #4833)
			var documentElement=(elem?elem.ownerDocument||elem:0).documentElement;			
			
			return documentElement?documentElement.nodeName!=="HTML":false;			
			
		};		
		
		var posProcess=function (selector,context){
			
			var match,
			tmpSet=[],
			later="",
			root=context.nodeType?[context]:context;			
			
			// Position selectors must be done after the filter
			// And so must :not(positional) so we move all PSEUDOs to the end
			while((match=Expr.match.PSEUDO.exec(selector))){
				
				later+=match[0];				
				selector=selector.replace(Expr.match.PSEUDO,"");				
				
			}

			
			selector=Expr.relative[selector]?selector+"*":selector;			
			
			for(var i=0,l=root.length;i<l;i++){
				
				Sizzle(selector,root[i],tmpSet);				
				
			}

			
			return Sizzle.filter(later,tmpSet);			
			
		};		
		
		// EXPOSE
		jQuery.find=Sizzle;		
		jQuery.expr=Sizzle.selectors;		
		jQuery.expr[":"]=jQuery.expr.filters;		
		jQuery.unique=Sizzle.uniqueSort;		
		jQuery.text=Sizzle.getText;		
		jQuery.isXMLDoc=Sizzle.isXML;		
		jQuery.contains=Sizzle.contains;		
		
		
		
	})();//#s5670-e7801	
	
	
	//1============================================================================================	
	
	
	var runtil=/Until$/,
	rparentsprev=/^(?:parents|prevUntil|prevAll)/,
	// Note: This RegExp should be improved, or likely pulled from Sizzle
	rmultiselector=/,/,
	isSimple=/^.[^:#\[\.,]*$/,
	slice=Array.prototype.slice,
	POS=jQuery.expr.match.POS,
	// methods guaranteed to produce a unique set when starting from a unique
	// set
	guaranteedUnique={
		
		children:true,
		contents:true,
		next:true,
		prev:true
		
	};	
	
	
	//1============================================================================================	
	
	
	jQuery.fn.extend({//#s7829-e8066
		
		/**
		 * 获得当前元素匹配集合中每个元素的后代，选择性筛选的选择器。
		 * 示例：$("p").find("span").css('color','red');//请先在body中添加<p><span>Hello</span>, how are you?</p>
		 */
		find:function (selector){//#s8139-e8196
			
			var self=this,
			i,l;			
			
			if(typeof selector!=="string"){
				
				return jQuery(selector).filter(function (){
					
					for(i=0,l=self.length;i<l;i++){
						
						if(jQuery.contains(self[i],this)){
							
							return true;							
							
						}
						
					}
					
				});				
				
			}

			
			var ret=this.pushStack("","find",selector),
			length,n,r;			
			
			for(i=0,l=this.length;i<l;i++){
				
				length=ret.length;				
				jQuery.find(selector,this[i],ret);				
				
				if(i>0){
					
					// Make sure that the results are unique
					for(n=length;n<ret.length;n++){
						
						for(r=0;r<length;r++){
							
							if(ret[r]===ret[n]){
								
								ret.splice(n--,1);								
								break;								
								
							}
							
						}
						
					}
					
				}
				
			}

			
			return ret;			
			
		},//#s8139-e8196
		
		/**
		 * 判断元素的后代中是否保留特定的元素
		 */
		has:function (target){
			
			var targets=jQuery(target);			
			return this.filter(function (){
				
				for(var i=0,l=targets.length;i<l;i++){
					
					if(jQuery.contains(this,targets[i])){
						
						return true;						
						
					}
					
				}
				
			});			
			
		},
		
		//获得元素中不匹配selector选择器的后代元素。
		not:function (selector){
			
			return this.pushStack(winnow(this,selector,false),"not",selector);			
			
		},
		
		//从元素中筛选出与指定表达式selector匹配的元素集合。
		filter:function (selector){
			
			return this.pushStack(winnow(this,selector,true),"filter",selector);			
			
		},
		
		//检查当前匹配的元素集合是否匹配选择器selector，如果这些元素至少一个匹配给定的参数，那么返回true。
		is:function (selector){
			
			return !!selector&&(typeof selector==="string"?
			jQuery.filter(selector,this).length>0:
			this.filter(selector).length>0);			
			
		},
		
		//从元素本身开始，逐级向上级元素匹配，并返回最先匹配的祖先元素。
		closest:function (selectors,context){
			
			var ret=[],i,l,cur=this[0];			
			
			// Array
			if(jQuery.isArray(selectors)){
				
				var match,selector,
				matches={
					
				},
				level=1;				
				
				if(cur&&selectors.length){
					
					for(i=0,l=selectors.length;i<l;i++){
						
						selector=selectors[i];						
						
						if(!matches[selector]){
							
							matches[selector]=POS.test(selector)?
							jQuery(selector,context||this.context):
							selector;							
							
						}
						
					}
					
					while(cur&&cur.ownerDocument&&cur!==context){
						
						for(selector in matches){
							
							match=matches[selector];							
							
							if(match.jquery?match.index(cur)>-1:jQuery(cur).is(match)){
								
								ret.push({
									selector:selector,elem:cur,level:level
								});								
								
							}
							
						}

						
						cur=cur.parentNode;						
						level++;						
						
					}
					
				}

				
				return ret;				
				
			}

			
			// String
			var pos=POS.test(selectors)||typeof selectors!=="string"?
			jQuery(selectors,context||this.context):
			0;			
			
			for(i=0,l=this.length;i<l;i++){
				
				cur=this[i];				
				
				while(cur){
					
					if(pos?pos.index(cur)>-1:jQuery.find.matchesSelector(cur,selectors)){
						
						ret.push(cur);						
						break;						
						
						
					}else {
						
						cur=cur.parentNode;						
						if(!cur||!cur.ownerDocument||cur===context||cur.nodeType===11){
							
							break;							
							
						}
						
					}
					
				}
				
			}

			
			ret=ret.length>1?jQuery.unique(ret):ret;			
			
			return this.pushStack(ret,"closest",selectors);			
			
		},
		
		// Determine the position of an element within
		// the matched set of elements
		//从匹配的元素中搜索给定元素的索引值，从0开始计数。
		index:function (elem){
			
			if(!elem||typeof elem==="string"){
				
				return jQuery.inArray(this[0],
				// If it receives a string, the selector is used
				// If it receives nothing, the siblings are used
				elem?jQuery(elem):this.parent().children());				
				
			}

			// Locate the position of the desired element
			return jQuery.inArray(
			// If it receives a jQuery object, the first element is used
			elem.jquery?elem[0]:elem,this);			
			
		},
		
		//添加元素到匹配的元素集合。
		add:function (selector,context){
			
			var set=typeof selector==="string"?
			jQuery(selector,context):
			jQuery.makeArray(selector&&selector.nodeType?[selector]:selector),
			all=jQuery.merge(this.get(),set);			
			
			return this.pushStack(isDisconnected(set[0])||isDisconnected(all[0])?
			all:
			jQuery.unique(all));			
			
		},
		
		//添加先前的堆栈元素集合到当前组合。
		andSelf:function (){
			
			return this.add(this.prevObject);			
			
		}
		
	});	//#s7829-e8066
	
	
	//1============================================================================================	
	
	
	// A painfully simple check to see if an element is disconnected
	// from a document (should be improved, where feasible).
	function isDisconnected(node){
		
		return !node||!node.parentNode||node.parentNode.nodeType===11;		
		
	}
	
	
	//1============================================================================================	

	
	jQuery.each({//#s8084-e8189
		
		//获得集合中每个匹配元素的父级元素，选择性筛选的选择器。
		parent:function (elem){
			
			var parent=elem.parentNode;			
			return parent&&parent.nodeType!==11?parent:null;			
			
		},
		
		//获得集合中每个匹配元素的祖先元素，选择性筛选的选择器
		parents:function (elem){
			
			return jQuery.dir(elem,"parentNode");			
			
		},
		
		//查找当前元素的所有的前辈元素，直到遇到选择器匹配的元素为止，不包括那个匹配到的元素。
		parentsUntil:function (elem,i,until){
			
			return jQuery.dir(elem,"parentNode",until);			
			
		},
		
		//取得一个包含匹配的元素集合中每一个元素紧邻的后面同辈元素的元素集合。如果提供一个选择器，它检索下一个匹配选择器的兄弟元素。
		next:function (elem){
			
			return jQuery.nth(elem,2,"nextSibling");			
			
		},
		
		//取得一个包含匹配的元素集合中每一个元素紧邻的前一个同辈元素的元素集合。选择性筛选的选择器。
		prev:function (elem){
			
			return jQuery.nth(elem,2,"previousSibling");			
			
		},
		
		//获得每个匹配元素集合中所有下面的同辈元素，选择性筛选的选择器。
		nextAll:function (elem){
			
			return jQuery.dir(elem,"nextSibling");			
			
		},
		
		//获得集合中每个匹配元素的所有前面的兄弟元素，选择性筛选的选择器。
		prevAll:function (elem){
			
			return jQuery.dir(elem,"previousSibling");			
			
		},
		
		//获取每个当前元素之后所有的同辈元素，但不包括选择器匹配的元素。
		nextUntil:function (elem,i,until){
			
			return jQuery.dir(elem,"nextSibling",until);			
			
		},
		
		//获取每个元素但不包括选择器匹配的元素的所有前面的兄弟元素。
		prevUntil:function (elem,i,until){
			
			return jQuery.dir(elem,"previousSibling",until);			
			
		},
		
		//获得匹配元素集合中每个元素的兄弟元素，选择性筛选的选择器。
		siblings:function (elem){
			
			return jQuery.sibling(elem.parentNode.firstChild,elem);			
			
		},
		
		//获得每个匹配元素集合元素的子元素，选择性筛选的选择器。
		children:function (elem){
			
			return jQuery.sibling(elem.firstChild);			
			
		},
		
		//获得每个匹配元素集合元素的子元素，包括文字和注释节点。
		contents:function (elem){
			
			return jQuery.nodeName(elem,"iframe")?
			elem.contentDocument||elem.contentWindow.document:
			jQuery.makeArray(elem.childNodes);			
			
		}
		
	},function (name,fn){
		
		jQuery.fn[name]=function (until,selector){
			
			var ret=jQuery.map(this,fn,until),
			// The variable 'args' was introduced in
			// https://github.com/jquery/jquery/commit/52a0238
			// to work around a bug in Chrome 10 (Dev) and should be removed
			// when the bug is fixed.
			// http://code.google.com/p/v8/issues/detail?id=1050
			args=slice.call(arguments);			
			
			if(!runtil.test(name)){
				
				selector=until;				
				
			}

			
			if(selector&&typeof selector==="string"){
				
				ret=jQuery.filter(selector,ret);				
				
			}

			
			ret=this.length>1&&!guaranteedUnique[name]?jQuery.unique(ret):ret;			
			
			if((this.length>1||rmultiselector.test(selector))&&rparentsprev.test(name)){
				
				ret=ret.reverse();				
				
			}

			
			return this.pushStack(ret,name,args.join(","));			
			
		};		
		
	});	//#s8084-e8189
	
	
	//1============================================================================================	
	
	
	jQuery.extend({//#s8195-e8272
		
		//筛选出与指定表达式匹配的元素集合。
		filter:function (expr,elems,not){
			
			if(not){
				
				expr=":not("+expr+")";				
				
			}

			
			return elems.length===1?
			jQuery.find.matchesSelector(elems[0],expr)?[elems[0]]:[]:
			jQuery.find.matches(expr,elems);			
			
		},
		
		dir:function (elem,dir,until){
			
			var matched=[],
			cur=elem[dir];			
			
			while(cur&&cur.nodeType!==9&&(until===undefined||cur.nodeType!==1||!jQuery(cur).is(until))){
				
				if(cur.nodeType===1){
					
					matched.push(cur);					
					
				}

				cur=cur[dir];				
				
			}

			return matched;			
			
		},
		
		nth:function (cur,result,dir,elem){
			
			result=result||1;			
			var num=0;			
			
			for(;cur;cur=cur[dir]){
				
				if(cur.nodeType===1&&++num===result){
					
					break;					
					
				}
				
			}

			
			return cur;			
			
		},
		
		sibling:function (n,elem){
			
			var r=[];			
			
			for(;n;n=n.nextSibling){
				
				if(n.nodeType===1&&n!==elem){
					
					r.push(n);					
					
				}
				
			}

			
			return r;			
			
		}
		
	});	//#s8195-e8272
	
	
	//1============================================================================================	
	
	
	// Implement the identical functionality for filter and not
	function winnow(elements,qualifier,keep){//#s8279-e8332
		
		
		// Can't pass null or undefined to indexOf in Firefox 4
		// Set to 0 to skip string check
		qualifier=qualifier||0;		
		
		if(jQuery.isFunction(qualifier)){
			
			return jQuery.grep(elements,function (elem,i){
				
				var retVal=!!qualifier.call(elem,i,elem);				
				return retVal===keep;				
				
			});			
			
			
		}else if(qualifier.nodeType){
			
			return jQuery.grep(elements,function (elem,i){
				
				return (elem===qualifier)===keep;				
				
			});			
			
			
		}else if(typeof qualifier==="string"){
			
			var filtered=jQuery.grep(elements,function (elem){
				
				return elem.nodeType===1;				
				
			});			
			
			if(isSimple.test(qualifier)){
				
				return jQuery.filter(qualifier,filtered,!keep);				
				
			}else {
				
				qualifier=jQuery.filter(qualifier,filtered);				
				
			}
			
		}

		
		return jQuery.grep(elements,function (elem,i){
			
			return (jQuery.inArray(elem,qualifier)>=0)===keep;			
			
		});		
		
	}//#s8279-e8332
	
	
	//1============================================================================================	
	
	
	var rinlinejQuery=/jQuery\d+="(?:\d+|null)"/g,
	rleadingWhitespace=/^\s+/,//匹配“左边的空白字符”
	rxhtmlTag=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
	rtagName=/<([\w:]+)/,//匹配标签名称
	rtbody=/<tbody/i,//匹配<tbody，不区分大小写。
	rhtml = /<|&#?\w+;/,
	rnocache=/<(?:script|object|embed|option|style)/i,//匹配含有<script、<object、<embed、<option或<style等的代码，不区分大小写。示例：var a="a<script b";
	// checked="checked" or checked
	rchecked=/checked\s*(?:[^=]|=\s*.checked.)/i,//匹配含有checked或checked="checked"等的代码，不区分大小写。
	rscriptType=/\/(java|ecma)script/i,
	rcleanScript=/^\s*<!(?:\[CDATA\[|\-\-)/,
	wrapMap={
		
		option:[1,"<select multiple='multiple'>","</select>"],
		legend:[1,"<fieldset>","</fieldset>"],
		thead:[1,"<table>","</table>"],
		tr:[2,"<table><tbody>","</tbody></table>"],
		td:[3,"<table><tbody><tr>","</tr></tbody></table>"],
		col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],
		area:[1,"<map>","</map>"],
		_default:[0,"",""]
		
	};	
	
	wrapMap.optgroup=wrapMap.option;	
	wrapMap.tbody=wrapMap.tfoot=wrapMap.colgroup=wrapMap.caption=wrapMap.thead;	
	wrapMap.th=wrapMap.td;	
	
	
	//1============================================================================================	
	
	
	// IE can't serialize <link> and <script> tags normally
	if(!jQuery.support.htmlSerialize){
		
		wrapMap._default=[1,"div<div>","</div>"];		
		
	}
	
	
	//1============================================================================================	

	
	jQuery.fn.extend({//#s8381-e8883
		
		//得到匹配元素集合中每个元素的文本内容结合,包括他们的后代文本。注意与.html()方法的区别
		//示例：(1)先在body中添加<p><b>Test</b> Paragraph.</p> (2)alert($("p:first").text());//弹出“Test Paragraph.”
		text:function (text){
			
			if(jQuery.isFunction(text)){
				
				return this.each(function (i){
					
					var self=jQuery(this);					
					
					self.text(text.call(this,i,self.text()));					
					
				});				
				
			}

			
			if(typeof text!=="object"&&text!==undefined){
				
				return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(text));				
				
			}

			
			return jQuery.text(this);			
			
		},
		
		//在所有匹配元素的外面包一层HTML结构：包在“外面”，所有匹配元素一起在“里面”
		//示例：
		//(1)开始：<div class="container"><div class="inner">Hello</div><div class="inner">Goodbye</div></div> 
		//(2)执行：$('.inner').wrapAll('<div class="new" />');
		//(3)结果：<div class="container"><div class="new"><div class="inner">Hello</div><div class="inner">Goodbye</div></div></div>
		wrapAll:function (html){
			
			if(jQuery.isFunction(html)){
				
				return this.each(function (i){
					
					jQuery(this).wrapAll(html.call(this,i));					
					
				});				
				
			}

			
			if(this[0]){
				
				// The elements to wrap the target around
				var wrap=jQuery(html,this[0].ownerDocument).eq(0).clone(true);				
				
				if(this[0].parentNode){
					
					wrap.insertBefore(this[0]);					
					
				}

				
				wrap.map(function (){
					
					var elem=this;					
					
					while(elem.firstChild&&elem.firstChild.nodeType===1){
						
						elem=elem.firstChild;						
						
					}

					
					return elem;					
					
				}).append(this);				
				
			}

			
			return this;			
			
		},
		
		//在匹配元素里的内容外包一层结构：匹配元素在“外面”，包在“里面”，注意与wrapAll方法的区别
		//示例：
		//(1)开始：<div class="container"><div class="inner">Hello</div><div class="inner">Goodbye</div></div> 
		//(2)执行：$('.inner').wrapInner('<div class="new" />');
		//(3)结果：<div class="container"><div class="inner"><div class="new">Hello</div></div><div class="inner"><div class="new">Goodbye</div></div></div>
		wrapInner:function (html){
			
			if(jQuery.isFunction(html)){
				
				return this.each(function (i){
					
					jQuery(this).wrapInner(html.call(this,i));					
					
				});				
				
			}

			
			return this.each(function (){
				
				var self=jQuery(this),
				contents=self.contents();				
				
				if(contents.length){
					
					contents.wrapAll(html);					
					
					
				}else {
					
					self.append(html);					
					
				}
				
			});			
			
		},
		
		//在每个匹配的元素外层包上一个html元素：包在“外面”，每个匹配元素分别在“里面”，注意与wrapAll方法的区别
		//示例：
		//(1)开始：<div class="container"><div class="inner">Hello</div><div class="inner">Goodbye</div></div> 
		//(2)执行：$('.inner').wrap('<div class="new" />');
		//(3)结果：<div class="container"><div class="new"><div class="inner">Hello</div></div><div class="new"><div class="inner">Goodbye</div></div></div>
		wrap:function (html){
			
			return this.each(function (){
				
				jQuery(this).wrapAll(html);				
				
			});			
			
		},
		
		//将匹配元素的父级元素删除，保留自身（和兄弟元素，如果存在）在原来的位置。.unwrap()删除元素的父级元素，和 .wrap()的功能相反。
		unwrap:function (){
			
			return this.parent().each(function (){
				
				if(!jQuery.nodeName(this,"body")){
					
					jQuery(this).replaceWith(this.childNodes);					
					
				}
				
			}).end();			
			
		},
		
		//根据参数设定在每个匹配元素里面的末尾处插入内容：匹配元素“里面的末尾”
		//示例：
		//(1)开始：<div class="container"><div class="inner">Hello</div><div class="inner">Goodbye</div></div> 
		//(2)执行：$('.inner').append('<p>Test</p>');
		//(3)结果：<div class="container"><div class="inner">Hello<p>Test</p></div><div class="inner">Goodbye<p>Test</p></div></div> 
		append:function (){
			
			return this.domManip(arguments,true,function (elem){
				
				if(this.nodeType===1){
					
					this.appendChild(elem);					
					
				}
				
			});			
			
		},
		
		//将参数内容插入到每个匹配元素的前面（元素内部）：匹配元素“里面的前面”
		//示例：
		//(1)开始：<div class="container"><div class="inner">Hello</div><div class="inner">Goodbye</div></div> 
		//(2)执行：$('.inner').prepend('<p>Test</p>');
		//(3)结果：<div class="container"><div class="inner"><p>Test</p>Hello</div><div class="inner"><p>Test</p>Goodbye</div></div> 
		prepend:function (){
			
			return this.domManip(arguments,true,function (elem){
				
				if(this.nodeType===1){
					
					this.insertBefore(elem,this.firstChild);					
					
				}
				
			});			
			
		},
		
		//根据参数设定在匹配元素的前面（外面）插入内容：匹配元素“外面的前面”
		//示例：
		//(1)开始：<div class="container"><div class="inner">Hello</div><div class="inner">Goodbye</div></div> 
		//(2)执行：$('.inner').before('<p>Test</p>');
		//(3)结果：<div class="container"><p>Test</p><div class="inner">Hello</div><p>Test</p><div class="inner">Goodbye</div></div> 
		before:function (){
			
			if(this[0]&&this[0].parentNode){
				
				return this.domManip(arguments,false,function (elem){
					
					this.parentNode.insertBefore(elem,this);					
					
				});				
				
			}else if(arguments.length){
				
				var set=jQuery(arguments[0]);				
				set.push.apply(set,this.toArray());				
				return this.pushStack(set,"before",arguments);				
				
			}
			
		},
		
		//根据参数设定在每一个匹配的元素之后（外面）插入内容：匹配元素“外面的后面”
		//示例：
		//(1)开始：<div class="container"><div class="inner">Hello</div><div class="inner">Goodbye</div></div> 
		//(2)执行：$('.inner').after('<p>Test</p>');
		//(3)结果：<div class="container"><div class="inner">Hello</div><p>Test</p><div class="inner">Goodbye</div><p>Test</p></div>
		after:function (){
			
			if(this[0]&&this[0].parentNode){
				
				return this.domManip(arguments,false,function (elem){
					
					this.parentNode.insertBefore(elem,this.nextSibling);					
					
				});				
				
			}else if(arguments.length){
				
				var set=this.pushStack(this,"after",arguments);				
				set.push.apply(set,jQuery(arguments[0]).toArray());				
				return set;				
				
			}
			
		},
		
		// keepData is for internal use only--do not document
		//将匹配元素从DOM中删除。和 .empty()相似，区别：.empty()是将元素内部清空但不将元素移除，.remove()是将元素移出DOM。
		//示例：
		//(1)开始：<div class="container"><div class="hello">Hello</div><div class="goodbye">Goodbye</div></div>
		//(2)执行：$('.hello').remove();
		//(3)结果：<div class="container"><div class="goodbye">Goodbye</div></div>
		remove:function (selector,keepData){
			
			for(var i=0,elem;(elem=this[i])!=null;i++){
				
				if(!selector||jQuery.filter(selector,[elem]).length){
					
					if(!keepData&&elem.nodeType===1){
						
						jQuery.cleanData(elem.getElementsByTagName("*"));						
						jQuery.cleanData([elem]);						
						
					}

					
					if(elem.parentNode){
						
						elem.parentNode.removeChild(elem);						
						
					}
					
				}
				
			}

			
			return this;			
			
		},
		
		//从DOM中移除所有节点的子节点，注意与.remove()方法的区别：.empty()仅将元素内部移出DOM但保留本身（即清空本身），.remove是连本身一起移出DOM
		//示例：
		//(1)开始：<div class="container"><div class="hello">Hello</div><div class="goodbye">Goodbye</div></div>
		//(2)执行：$('.hello').empty();
		//(3)结果：<div class="container"><div class="hello"></div><div class="goodbye">Goodbye</div></div>
		empty:function (){
			
			for(var i=0,elem;(elem=this[i])!=null;i++){
				
				// Remove element nodes and prevent memory leaks
				if(elem.nodeType===1){
					
					jQuery.cleanData(elem.getElementsByTagName("*"));					
					
				}

				
				// Remove any remaining nodes
				while(elem.firstChild){
					
					elem.removeChild(elem.firstChild);					
					
				}
				
			}

			
			return this;			
			
		},
		
		//深度复制所有匹配的元素
		clone:function (dataAndEvents,deepDataAndEvents){
			
			dataAndEvents=dataAndEvents==null?false:dataAndEvents;			
			deepDataAndEvents=deepDataAndEvents==null?dataAndEvents:deepDataAndEvents;			
			
			return this.map(function (){
				
				return jQuery.clone(this,dataAndEvents,deepDataAndEvents);				
				
			});			
			
		},
		
		//从匹配的第一个元素中获取HTML内容。注意与.text()方法的区别
		//示例：(1)先在body中添加<p><b>Test</b> Paragraph.</p> (2)alert($("p:first").html());//弹出“<b>Test</b> Paragraph.”
		html:function (value){
			
			if(value===undefined){
				
				return this[0]&&this[0].nodeType===1?
				this[0].innerHTML.replace(rinlinejQuery,""):
				null;				
				
				// See if we can take a shortcut and just use innerHTML
				
			}else if(typeof value==="string"&&!rnocache.test(value)&&
			(jQuery.support.leadingWhitespace||!rleadingWhitespace.test(value))&&
			!wrapMap[(rtagName.exec(value)||["",""])[1].toLowerCase()]){
				
				
				value=value.replace(rxhtmlTag,"<$1></$2>");				
				
				try{
					
					for(var i=0,l=this.length;i<l;i++){
						
						// Remove element nodes and prevent memory leaks
						if(this[i].nodeType===1){
							
							jQuery.cleanData(this[i].getElementsByTagName("*"));							
							this[i].innerHTML=value;							
							
						}
						
					}

					
					// If using innerHTML throws an exception, use the fallback method
					
				}catch(e){
					
					this.empty().append(value);					
					
				}
				
				
			}else if(jQuery.isFunction(value)){
				
				this.each(function (i){
					
					var self=jQuery(this);					
					
					self.html(value.call(this,i,self.html()));					
					
				});				
				
				
			}else {
				
				this.empty().append(value);				
				
			}

			
			return this;			
			
		},
		
		//用提供的内容替换所有匹配的元素。
		//示例：
		//(1)开始：<div class="container"><div class="first">Hello</div><div class="second">And</div><div class="third">Goodbye</div></div>
		//(2)执行：$('.second').replaceWith('<h2>New heading</h2>');
		//(3)结果：<div class="container"><div class="first">Hello</div><h2>New heading</h2><div class="third">Goodbye</div></div>
		replaceWith:function (value){
			
			if(this[0]&&this[0].parentNode){
				
				// Make sure that the elements are removed from the DOM before they
				// are inserted
				// this can help fix replacing a parent with child elements
				if(jQuery.isFunction(value)){
					
					return this.each(function (i){
						
						var self=jQuery(this),old=self.html();						
						self.replaceWith(value.call(this,i,old));						
						
					});					
					
				}

				
				if(typeof value!=="string"){
					
					value=jQuery(value).detach();					
					
				}

				
				return this.each(function (){
					
					var next=this.nextSibling,
					parent=this.parentNode;					
					
					jQuery(this).remove();					
					
					if(next){
						
						jQuery(next).before(value);						
						
					}else {
						
						jQuery(parent).append(value);						
						
					}
					
				});				
				
			}else {
				
				return this.length?
				this.pushStack(jQuery(jQuery.isFunction(value)?value():value),"replaceWith",value):
				this;				
				
			}
			
		},
		
		//从DOM是去掉所有匹配的元素
		detach:function (selector){
			
			return this.remove(selector,true);			
			
		},
		
		//
		domManip:function (args,table,callback){
			
			var results,first,fragment,parent,
			value=args[0],
			scripts=[];			
			
			// We can't cloneNode fragments that contain checked, in WebKit
			if(!jQuery.support.checkClone&&arguments.length===3&&typeof value==="string"&&rchecked.test(value)){
				
				return this.each(function (){
					
					jQuery(this).domManip(args,table,callback,true);					
					
				});				
				
			}

			
			if(jQuery.isFunction(value)){
				
				return this.each(function (i){
					
					var self=jQuery(this);					
					args[0]=value.call(this,i,table?self.html():undefined);					
					self.domManip(args,table,callback);					
					
				});				
				
			}

			
			if(this[0]){
				
				parent=value&&value.parentNode;				
				
				// If we're in a fragment, just use that instead of building a new
				// one
				if(jQuery.support.parentNode&&parent&&parent.nodeType===11&&parent.childNodes.length===this.length){
					
					results={
						fragment:parent
					};					
					
					
				}else {
					
					results=jQuery.buildFragment(args,this,scripts);					
					
				}

				
				fragment=results.fragment;				
				
				if(fragment.childNodes.length===1){
					
					first=fragment=fragment.firstChild;					
					
				}else {
					
					first=fragment.firstChild;					
					
				}

				
				if(first){
					
					table=table&&jQuery.nodeName(first,"tr");					
					
					for(var i=0,l=this.length,lastIndex=l-1;i<l;i++){
						
						callback.call(
						table?
						root(this[i],first):
						this[i],
						// Make sure that we do not leak memory by inadvertently
						// discarding
						// the original fragment (which might have attached
						// data) instead of
						// using it; in addition, use the original fragment
						// object for the last
						// item instead of first because it can end up being
						// emptied incorrectly
						// in certain situations (Bug #8070).
						// Fragments from the fragment cache must always be
						// cloned and never used
						// in place.
						results.cacheable||(l>1&&i<lastIndex)?
						jQuery.clone(fragment,true,true):
						fragment
						);						
						
					}
					
				}

				
				if(scripts.length){
					
					jQuery.each(scripts,evalScript);					
					
				}
				
			}

			
			return this;			
			
		}
		
	});	//#s8381-e8883
	
	
	//1============================================================================================	
	
	
	function root(elem,cur){
		
		return jQuery.nodeName(elem,"table")?
		(elem.getElementsByTagName("tbody")[0]||
		elem.appendChild(elem.ownerDocument.createElement("tbody"))):
		elem;		
		
	}
	
	
	//1============================================================================================	

	
	function cloneCopyEvent(src,dest){//#s8902-e8946
		
		
		if(dest.nodeType!==1||!jQuery.hasData(src)){
			
			return ;			
			
		}

		
		var internalKey=jQuery.expando,
		oldData=jQuery.data(src),
		curData=jQuery.data(dest,oldData);		
		
		// Switch to use the internal data object, if it exists, for the next
		// stage of data copying
		if((oldData=oldData[internalKey])){
			
			var events=oldData.events;			
			curData=curData[internalKey]=jQuery.extend({
				
			},oldData);			
			
			if(events){
				
				delete curData.handle;				
				curData.events={
					
				};				
				
				for(var type in events){
					
					for(var i=0,l=events[type].length;i<l;i++){
						
						jQuery.event.add(dest,type+(events[type][i].namespace?".":"")+events[type][i].namespace,events[type][i],events[type][i].data);						
						
					}
					
				}
				
			}
			
		}
		
	}//#s8902-e8946
	
	
	//1============================================================================================	

	
	function cloneFixAttributes(src,dest){//#s8952-e9034
		
		var nodeName;		
		
		// We do not need to do anything for non-Elements
		if(dest.nodeType!==1){
			
			return ;			
			
		}

		
		// clearAttributes removes the attributes, which we don't want,
		// but also removes the attachEvent events, which we *do* want
		if(dest.clearAttributes){
			
			dest.clearAttributes();			
			
		}

		
		// mergeAttributes, in contrast, only merges back on the
		// original attributes, not the events
		if(dest.mergeAttributes){
			
			dest.mergeAttributes(src);			
			
		}

		
		nodeName=dest.nodeName.toLowerCase();		
		
		// IE6-8 fail to clone children inside object elements that use
		// the proprietary classid attribute value (rather than the type
		// attribute) to identify the type of content to display
		if(nodeName==="object"){
			
			dest.outerHTML=src.outerHTML;			
			
			
		}else if(nodeName==="input"&&(src.type==="checkbox"||src.type==="radio")){
			
			// IE6-8 fails to persist the checked state of a cloned checkbox
			// or radio button. Worse, IE6-7 fail to give the cloned element
			// a checked appearance if the defaultChecked value isn't also set
			if(src.checked){
				
				dest.defaultChecked=dest.checked=src.checked;				
				
			}

			
			// IE6-7 get confused and end up setting the value of a cloned
			// checkbox/radio button to an empty string instead of "on"
			if(dest.value!==src.value){
				
				dest.value=src.value;				
				
			}

			
			// IE6-8 fails to return the selected option to the default selected
			// state when cloning options
			
		}else if(nodeName==="option"){
			
			dest.selected=src.defaultSelected;			
			
			// IE6-8 fails to set the defaultValue to the correct value when
			// cloning other types of input fields
			
		}else if(nodeName==="input"||nodeName==="textarea"){
			
			dest.defaultValue=src.defaultValue;			
			
		}

		
		// Event data gets referenced instead of copied if the expando
		// gets copied too
		dest.removeAttribute(jQuery.expando);		
		
	}//#s8952-e9034
	
	
	//1============================================================================================	

	
	jQuery.buildFragment=function (args,nodes,scripts){//#s9040-e9107
		
		var fragment,cacheable,cacheresults,doc;		
		
		// nodes may contain either an explicit document object,
		// a jQuery collection or context object.
		// If nodes[0] contains a valid object to assign to doc
		// 参数nodes可能包含一个明确的文档对象、jQuery集合或者上下文对象。
		// 判断nodes[0]是否包含一个有效的对象，并把此对象赋给doc变量。
		if(nodes&&nodes[0]){
			
			doc=nodes[0].ownerDocument||nodes[0];			
			
		}

		
		// Ensure that an attr object doesn't incorrectly stand in as a document
		// object
		// Chrome and Firefox seem to allow this to occur and will throw exception
		// Fixes #8950
		if(!doc.createDocumentFragment){
			
			doc=document;			
			
		}

		
		// Only cache "small" (1/2 KB) HTML strings that are associated with the
		// main document
		// Cloning options loses the selected state, so don't cache them
		// IE 6 doesn't like it when you put <object> or <embed> elements in a
		// fragment
		// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't
		// cache
		if(args.length===1&&typeof args[0]==="string"&&args[0].length<512&&doc===document&&
		args[0].charAt(0)==="<"&&!rnocache.test(args[0])&&(jQuery.support.checkClone||!rchecked.test(args[0]))){
			
			
			cacheable=true;			
			
			cacheresults=jQuery.fragments[args[0]];			
			if(cacheresults&&cacheresults!==1){
				
				fragment=cacheresults;				
				
			}
			
		}

		
		if(!fragment){
			
			fragment=doc.createDocumentFragment();			
			jQuery.clean(args,doc,fragment,scripts);			
			
		}

		
		if(cacheable){
			
			jQuery.fragments[args[0]]=cacheresults?fragment:1;			
			
		}

		
		return {
			fragment:fragment,cacheable:cacheable
		};		
		
	};//#s9040-e9107
	
	
	//1============================================================================================	
	
	
	jQuery.fragments={
		
	};
	
	
	//1============================================================================================	
	

	/**
	 * 这里为jQuery增加多个非常有用的方法：
	 * (1)appendTo方法：
	 * (2)prependTo方法：
	 * (3)insertBefore方法：
	 * (4)insertAfter方法：
	 * (5)replaceAll方法：
	 */
	jQuery.each({//#s9121-e9160
		
		appendTo:"append",
		prependTo:"prepend",
		insertBefore:"before",
		insertAfter:"after",
		replaceAll:"replaceWith"
		
	},function (name,original){
		
		jQuery.fn[name]=function (selector){
			
			var ret=[],
			insert=jQuery(selector),
			parent=this.length===1&&this[0].parentNode;			
			
			if(parent&&parent.nodeType===11&&parent.childNodes.length===1&&insert.length===1){
				
				insert[original](this[0]);				
				return this;				
				
				
			}else {
				
				for(var i=0,l=insert.length;i<l;i++){
					
					var elems=(i>0?this.clone(true):this).get();					
					jQuery(insert[i])[original](elems);					
					ret=ret.concat(elems);					
					
				}

				
				return this.pushStack(ret,name,insert.selector);				
				
			}
			
		};		
		
	});	//#s9121-e9160
	
	
	//1============================================================================================	
	
	
	function getAll(elem){//#s9166-e9184
		
		if("getElementsByTagName" in elem){
			
			return elem.getElementsByTagName("*");			
			
			
		}else if("querySelectorAll" in elem){
			
			return elem.querySelectorAll("*");			
			
			
		}else {
			
			return [];			
			
		}
		
	}//#s9166-e9184
	
	
	//1============================================================================================	

	
	// Used in clean, fixes the defaultChecked property
	function fixDefaultChecked(elem){//#s9191-e9199
		
		if(elem.type==="checkbox"||elem.type==="radio"){
			
			elem.defaultChecked=elem.checked;			
			
		}
		
	}//#s9191-e9199
	
	
	//1============================================================================================	
	

	// Finds all inputs and passes them to fixDefaultChecked
	function findInputs(elem){//#s9206-e9218
		
		if(jQuery.nodeName(elem,"input")){
			
			fixDefaultChecked(elem);			
			
		}else if("getElementsByTagName" in elem){
			
			jQuery.grep(elem.getElementsByTagName("input"),fixDefaultChecked);			
			
		}
		
	}//#s9206-e9218
	
	
	//1============================================================================================	

	
	jQuery.extend({//#s9224-e9536
		
		//深度复制所有匹配的元素
		clone:function (elem,dataAndEvents,deepDataAndEvents){
			
			var clone=elem.cloneNode(true),
			srcElements,
			destElements,
			i;			
			
			if((!jQuery.support.noCloneEvent||!jQuery.support.noCloneChecked)&&
			(elem.nodeType===1||elem.nodeType===11)&&!jQuery.isXMLDoc(elem)){
				
				// IE copies events bound via attachEvent when using cloneNode.
				// Calling detachEvent on the clone will also remove the events
				// from the original. In order to get around this, we use some
				// proprietary methods to clear the events. Thanks to MooTools
				// guys for this hotness.
				
				cloneFixAttributes(elem,clone);				
				
				// Using Sizzle here is crazy slow, so we use getElementsByTagName
				// instead
				srcElements=getAll(elem);				
				destElements=getAll(clone);				
				
				// Weird iteration because IE will replace the length property
				// with an element if you are cloning the body and one of the
				// elements on the page has a name or id of "length"
				for(i=0;srcElements[i];++i){
					
					cloneFixAttributes(srcElements[i],destElements[i]);					
					
				}
				
			}

			
			// Copy the events from the original to the clone
			if(dataAndEvents){
				
				cloneCopyEvent(elem,clone);				
				
				if(deepDataAndEvents){
					
					srcElements=getAll(elem);					
					destElements=getAll(clone);					
					
					for(i=0;srcElements[i];++i){
						
						cloneCopyEvent(srcElements[i],destElements[i]);						
						
					}
					
				}
				
			}

			
			srcElements=destElements=null;			
			
			// Return the cloned set
			return clone;			
			
		},
		
		//
		clean:function (elems,context,fragment,scripts){
			
			var checkScriptType;			
			
			context=context||document;			
			
			// !context.createElement fails in IE with an error but returns typeof
			// 'object'
			if(typeof context.createElement==="undefined"){
				
				context=context.ownerDocument||context[0]&&context[0].ownerDocument||document;				
				
			}

			
			var ret=[],j;			
			
			for(var i=0,elem;(elem=elems[i])!=null;i++){
				
				if(typeof elem==="number"){
					
					elem+="";					
					
				}

				
				if(!elem){
					
					continue;					
					
				}

				
				// Convert html string into DOM nodes
				if(typeof elem==="string"){
					
					if(!rhtml.test(elem)){
						
						elem=context.createTextNode(elem);						
						
					}else {
						
						// Fix "XHTML"-style tags in all browsers
						elem=elem.replace(rxhtmlTag,"<$1></$2>");						
						
						// Trim whitespace, otherwise indexOf won't work as expected
						var tag=(rtagName.exec(elem)||["",""])[1].toLowerCase(),
						wrap=wrapMap[tag]||wrapMap._default,
						depth=wrap[0],
						div=context.createElement("div");						
						
						// Go to html and back, then peel off extra wrappers
						div.innerHTML=wrap[1]+elem+wrap[2];						
						
						// Move to the right depth
						while(depth--){
							
							div=div.lastChild;							
							
						}

						
						// Remove IE's autoinserted <tbody> from table fragments
						if(!jQuery.support.tbody){
							
							
							// String was a <table>, *may* have spurious <tbody>
							var hasBody=rtbody.test(elem),
							tbody=tag==="table"&&!hasBody?
							div.firstChild&&div.firstChild.childNodes:
							
							// String was a bare <thead> or <tfoot>
							wrap[1]==="<table>"&&!hasBody?
							div.childNodes:
							[];							
							
							for(j=tbody.length-1;j>=0;--j){
								
								if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length){
									
									tbody[j].parentNode.removeChild(tbody[j]);									
									
								}
								
							}
							
						}

						
						// IE completely kills leading whitespace when innerHTML is
						// used
						if(!jQuery.support.leadingWhitespace&&rleadingWhitespace.test(elem)){
							
							div.insertBefore(context.createTextNode(rleadingWhitespace.exec(elem)[0]),div.firstChild);							
							
						}

						
						elem=div.childNodes;						
						
					}
					
				}

				
				// Resets defaultChecked for any radios and checkboxes
				// about to be appended to the DOM in IE 6/7 (#8060)
				var len;				
				if(!jQuery.support.appendChecked){
					
					if(elem[0]&&typeof (len=elem.length)==="number"){
						
						for(j=0;j<len;j++){
							
							findInputs(elem[j]);							
							
						}
						
					}else {
						
						findInputs(elem);						
						
					}
					
				}

				
				if(elem.nodeType){
					
					ret.push(elem);					
					
				}else {
					
					ret=jQuery.merge(ret,elem);					
					
				}
				
			}

			
			if(fragment){
				
				checkScriptType=function (elem){
					
					return !elem.type||rscriptType.test(elem.type);					
					
				};				
				for(i=0;ret[i];i++){
					
					if(scripts&&jQuery.nodeName(ret[i],"script")&&(!ret[i].type||ret[i].type.toLowerCase()==="text/javascript")){
						
						scripts.push(ret[i].parentNode?ret[i].parentNode.removeChild(ret[i]):ret[i]);						
						
						
					}else {
						
						if(ret[i].nodeType===1){
							
							var jsTags=jQuery.grep(ret[i].getElementsByTagName("script"),checkScriptType);							
							
							ret.splice.apply(ret,[i+1,0].concat(jsTags));							
							
						}

						fragment.appendChild(ret[i]);						
						
					}
					
				}
				
			}

			
			return ret;			
			
		},
		
		//
		cleanData:function (elems){
			
			var data,id,cache=jQuery.cache,internalKey=jQuery.expando,special=jQuery.event.special,
			deleteExpando=jQuery.support.deleteExpando;			
			
			for(var i=0,elem;(elem=elems[i])!=null;i++){
				
				if(elem.nodeName&&jQuery.noData[elem.nodeName.toLowerCase()]){
					
					continue;					
					
				}

				
				id=elem[jQuery.expando];				
				
				if(id){
					
					data=cache[id]&&cache[id][internalKey];					
					
					if(data&&data.events){
						
						for(var type in data.events){
							
							if(special[type]){
								
								jQuery.event.remove(elem,type);								
								
								// This is a shortcut to avoid jQuery.event.remove's
								// overhead
								
							}else {
								
								jQuery.removeEvent(elem,type,data.handle);								
								
							}
							
						}

						
						// Null the DOM reference to avoid IE6/7/8 leak (#7054)
						if(data.handle){
							
							data.handle.elem=null;							
							
						}
						
					}

					
					if(deleteExpando){
						
						delete elem[jQuery.expando];						
						
						
					}else if(elem.removeAttribute){
						
						elem.removeAttribute(jQuery.expando);						
						
					}

					
					delete cache[id];					
					
				}
				
			}
			
		}
		
	});	//#s9224-e9536
	
	
	//1============================================================================================	
	
	
	function evalScript(i,elem){//#9542-e9567
		
		if(elem.src){
			
			jQuery.ajax({
				
				url:elem.src,
				async:false,
				dataType:"script"
				
			});			
			
		}else {
			
			jQuery.globalEval((elem.text||elem.textContent||elem.innerHTML||"").replace(rcleanScript,"/*$0*/"));			
			
		}

		
		if(elem.parentNode){
			
			elem.parentNode.removeChild(elem);			
			
		}
		
	}//#9542-e9567
	
	
	//1============================================================================================	
	
	
	var ralpha=/alpha\([^)]*\)/i,
	ropacity=/opacity=([^)]*)/,
	// fixed for IE9, see #8346
	rupper=/([A-Z]|^ms)/g,
	rnumpx=/^-?\d+(?:px)?$/i,
	rnum=/^-?\d/,
	rrelNum=/^[+\-]=/,
	rrelNumFilter=/[^+\-\.\de]+/g,
	
	cssShow={
		position:"absolute",visibility:"hidden",display:"block"
	},
	cssWidth=["Left","Right"],
	cssHeight=["Top","Bottom"],
	curCSS,
	
	getComputedStyle,
	currentStyle;
	
	
	//1============================================================================================	
	
	
	jQuery.fn.css=function (name,value){//#s9596-e9614
		
		// Setting 'undefined' is a no-op
		if(arguments.length===2&&value===undefined){
			
			return this;			
			
		}

		
		return jQuery.access(this,name,value,true,function (elem,name,value){
			
			return value!==undefined?
			jQuery.style(elem,name,value):
			jQuery.css(elem,name);			
			
		});		
		
	};
	
	
	//1============================================================================================	
	
	
	jQuery.extend({//#s9620-e9817
		
		// Add in style property hooks for overriding the default
		// behavior of getting and setting a style property
		cssHooks:{
			
			opacity:{
				
				get:function (elem,computed){
					
					if(computed){
						
						// We should always get a number back from opacity
						var ret=curCSS(elem,"opacity","opacity");						
						return ret===""?"1":ret;						
						
						
					}else {
						
						return elem.style.opacity;						
						
					}
					
				}
				
			}
			
		},
		
		// Exclude the following css properties to add px
		cssNumber:{
			
			"fillOpacity":true,
			"fontWeight":true,
			"lineHeight":true,
			"opacity":true,
			"orphans":true,
			"widows":true,
			"zIndex":true,
			"zoom":true
			
		},
		
		// Add in properties whose names you wish to fix before
		// setting or getting the value
		cssProps:{
			
			// normalize float css property
			"float":jQuery.support.cssFloat?"cssFloat":"styleFloat"
			
		},
		
		// Get and set the style property on a DOM Node
		style:function (elem,name,value,extra){
			
			// Don't set styles on text and comment nodes
			if(!elem||elem.nodeType===3||elem.nodeType===8||!elem.style){
				
				return ;				
				
			}

			
			// Make sure that we're working with the right name
			var ret,type,origName=jQuery.camelCase(name),
			style=elem.style,hooks=jQuery.cssHooks[origName];			
			
			name=jQuery.cssProps[origName]||origName;			
			
			// Check if we're setting a value
			if(value!==undefined){
				
				type=typeof value;				
				
				// Make sure that NaN and null values aren't set. See: #7116
				if(type==="number"&&isNaN(value)||value==null){
					
					return ;					
					
				}

				
				// convert relative number strings (+= or -=) to relative numbers.
				// #7345
				if(type==="string"&&rrelNum.test(value)){
					
					value=+value.replace(rrelNumFilter,"")+parseFloat(jQuery.css(elem,name));					
					// Fixes bug #9237
					type="number";					
					
				}

				
				// If a number was passed in, add 'px' to the (except for certain
				// CSS properties)
				if(type==="number"&&!jQuery.cssNumber[origName]){
					
					value+="px";					
					
				}

				
				// If a hook was provided, use that value, otherwise just set the
				// specified value
				if(!hooks||!("set" in hooks)||(value=hooks.set(elem,value))!==undefined){
					
					// Wrapped to prevent IE from throwing errors when 'invalid'
					// values are provided
					// Fixes bug #5509
					try{
						
						style[name]=value;						
						
					}catch(e){
						
					}
					
				}
				
				
			}else {
				
				// If a hook was provided get the non-computed value from there
				if(hooks&&"get" in hooks&&(ret=hooks.get(elem,false,extra))!==undefined){
					
					return ret;					
					
				}

				
				// Otherwise just get the value from the style object
				return style[name];				
				
			}
			
		},
		
		css:function (elem,name,extra){
			
			var ret,hooks;			
			
			// Make sure that we're working with the right name
			name=jQuery.camelCase(name);			
			hooks=jQuery.cssHooks[name];			
			name=jQuery.cssProps[name]||name;			
			
			// cssFloat needs a special treatment
			if(name==="cssFloat"){
				
				name="float";				
				
			}

			
			// If a hook was provided get the computed value from there
			if(hooks&&"get" in hooks&&(ret=hooks.get(elem,true,extra))!==undefined){
				
				return ret;				
				
				// Otherwise, if a way to get the computed value exists, use that
				
			}else if(curCSS){
				
				return curCSS(elem,name);				
				
			}
			
		},
		
		// A method for quickly swapping in/out CSS properties to get correct
		// calculations
		swap:function (elem,options,callback){
			
			var old={
				
			};			
			
			// Remember the old values, and insert the new ones
			for(var name in options){
				
				old[name]=elem.style[name];				
				elem.style[name]=options[name];				
				
			}

			
			callback.call(elem);			
			
			// Revert the old values
			for(name in options){
				
				elem.style[name]=old[name];				
				
			}
			
		}
		
	});	//#s9620-e9817
	
	
	//1============================================================================================	
	
	
	// DEPRECATED, Use jQuery.css() instead
	jQuery.curCSS=jQuery.css;
	
	
	//1============================================================================================	
	

	/**
	 * 这里为jQuery增加两个非常有用的方法：
	 * (1)height方法：为匹配的元素集合中获取第一个元素的当前计算高度值。
	 * 	示例：
	 * $(window).height(); //浏览器当前窗口可视区域高度
	 * $(document).height(); //浏览器当前窗口文档的高度
	 * $(document.body).height();//浏览器当前窗口文档body的高度
	 * $(document.body).outerHeight(true);//浏览器当前窗口文档body的总高度 包括border padding margin
	 * 
	 * (2)width方法：为匹配的元素集合中获取第一个元素的当前计算宽度值。
	 * 	示例：
	 * $(window).width(); //浏览器当前窗口可视区域宽度
	 * $(document).width();//浏览器当前窗口文档对象宽度
	 * $(document.body).width();//浏览器当前窗口文档body的高度
	 * $(document.body).outerWidth(true);//浏览器当前窗口文档body的总宽度 包括border padding margin
	 */
	jQuery.each(["height","width"],function (i,name){//#s9830-e9885
		
		jQuery.cssHooks[name]={
			
			get:function (elem,computed,extra){
				
				var val;				
				
				if(computed){
					
					if(elem.offsetWidth!==0){
						
						return getWH(elem,name,extra);						
						
					}else {
						
						jQuery.swap(elem,cssShow,function (){
							
							val=getWH(elem,name,extra);							
							
						});						
						
					}

					
					return val;					
					
				}
				
			},
			
			set:function (elem,value){
				
				if(rnumpx.test(value)){
					
					// ignore negative width and height values #1599
					value=parseFloat(value);					
					
					if(value>=0){
						
						return value+"px";						
						
					}
					
					
				}else {
					
					return value;					
					
				}
				
			}
			
		};		
		
	});	//#s9830-e9885
	
	
	//1============================================================================================	
	
	
	if(!jQuery.support.opacity){//#s9891-e9927
		
		jQuery.cssHooks.opacity={
			
			get:function (elem,computed){
				
				// IE uses filters for opacity
				return ropacity.test((computed&&elem.currentStyle?elem.currentStyle.filter:elem.style.filter)||"")?
				(parseFloat(RegExp.$1)/100)+"":
				computed?"1":"";				
				
			},
			
			set:function (elem,value){
				
				var style=elem.style,
				currentStyle=elem.currentStyle;				
				
				// IE has trouble with opacity if it does not have layout
				// Force it by setting the zoom level
				style.zoom=1;				
				
				// Set the alpha filter to set the opacity
				var opacity=jQuery.isNaN(value)?
				"":
				"alpha(opacity="+value*100+")",
				filter=currentStyle&&currentStyle.filter||style.filter||"";				
				
				style.filter=ralpha.test(filter)?
				filter.replace(ralpha,opacity):
				filter+" "+opacity;				
				
			}
			
		};		
		
	}//#s9891-e9927
	
	
	//1============================================================================================	

	
	jQuery(function (){//#s9933-e9971
		
		// This hook cannot be added until DOM ready because the support test
		// for it is not run until after DOM ready
		if(!jQuery.support.reliableMarginRight){
			
			jQuery.cssHooks.marginRight={
				
				get:function (elem,computed){
					
					// WebKit Bug 13343 - getComputedStyle returns wrong value for
					// margin-right
					// Work around by temporarily setting element display to
					// inline-block
					var ret;					
					jQuery.swap(elem,{
						"display":"inline-block"
					},function (){
						
						if(computed){
							
							ret=curCSS(elem,"margin-right","marginRight");							
							
						}else {
							
							ret=elem.style.marginRight;							
							
						}
						
					});					
					return ret;					
					
				}
				
			};			
			
		}
		
	});//#s9933-e9971	
	
	
	//1============================================================================================	
	
	
	if(document.defaultView&&document.defaultView.getComputedStyle){//#s9977-e10008
		
		getComputedStyle=function (elem,name){
			
			var ret,defaultView,computedStyle;			
			
			name=name.replace(rupper,"-$1").toLowerCase();			
			
			if(!(defaultView=elem.ownerDocument.defaultView)){
				
				return undefined;				
				
			}

			
			if((computedStyle=defaultView.getComputedStyle(elem,null))){
				
				ret=computedStyle.getPropertyValue(name);				
				if(ret===""&&!jQuery.contains(elem.ownerDocument.documentElement,elem)){
					
					ret=jQuery.style(elem,name);					
					
				}
				
			}

			
			return ret;			
			
		};		
		
	}//#s9977-e10008
	
	
	//1============================================================================================	

	
	if(document.documentElement.currentStyle){//#s10014-e10058
		
		currentStyle=function (elem,name){
			
			var left,
			ret=elem.currentStyle&&elem.currentStyle[name],
			rsLeft=elem.runtimeStyle&&elem.runtimeStyle[name],
			style=elem.style;			
			
			// From the awesome hack by Dean Edwards
			// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
			
			// If we're not dealing with a regular pixel number
			// but a number that has a weird ending, we need to convert it to pixels
			if(!rnumpx.test(ret)&&rnum.test(ret)){
				
				// Remember the original values
				left=style.left;				
				
				// Put in the new values to get a computed value out
				if(rsLeft){
					
					elem.runtimeStyle.left=elem.currentStyle.left;					
					
				}

				style.left=name==="fontSize"?"1em":(ret||0);				
				ret=style.pixelLeft+"px";				
				
				// Revert the changed values
				style.left=left;				
				if(rsLeft){
					
					elem.runtimeStyle.left=rsLeft;					
					
				}
				
			}

			
			return ret===""?"auto":ret;			
			
		};		
		
	}//#s10014-e10058
	
	
	//1============================================================================================	

	
	curCSS=getComputedStyle||currentStyle;	
	
	
	//1============================================================================================	
	
	
	function getWH(elem,name,extra){//#s10070-e10145
		
		
		// Start with offset property
		var val=name==="width"?elem.offsetWidth:elem.offsetHeight,
		which=name==="width"?cssWidth:cssHeight;		
		
		if(val>0){
			
			if(extra!=="border"){
				
				jQuery.each(which,function (){
					
					if(!extra){
						
						val-=parseFloat(jQuery.css(elem,"padding"+this))||0;						
						
					}

					if(extra==="margin"){
						
						val+=parseFloat(jQuery.css(elem,extra+this))||0;						
						
					}else {
						
						val-=parseFloat(jQuery.css(elem,"border"+this+"Width"))||0;						
						
					}
					
				});				
				
			}

			
			return val+"px";			
			
		}

		
		// Fall back to computed then uncomputed css if necessary
		val=curCSS(elem,name,name);		
		if(val<0||val==null){
			
			val=elem.style[name]||0;			
			
		}

		// Normalize "", auto, and prepare for extra
		val=parseFloat(val)||0;		
		
		// Add padding, border, margin
		if(extra){
			
			jQuery.each(which,function (){
				
				val+=parseFloat(jQuery.css(elem,"padding"+this))||0;				
				if(extra!=="padding"){
					
					val+=parseFloat(jQuery.css(elem,"border"+this+"Width"))||0;					
					
				}

				if(extra==="margin"){
					
					val+=parseFloat(jQuery.css(elem,extra+this))||0;					
					
				}
				
			});			
			
		}

		
		return val+"px";		
		
	}//#s10070-e10145
	
	
	//1============================================================================================	

	
	if(jQuery.expr&&jQuery.expr.filters){//#s10151-e10168
		
		jQuery.expr.filters.hidden=function (elem){
			
			var width=elem.offsetWidth,
			height=elem.offsetHeight;			
			
			return (width===0&&height===0)||(!jQuery.support.reliableHiddenOffsets&&(elem.style.display||jQuery.css(elem,"display"))==="none");			
			
		};		
		
		jQuery.expr.filters.visible=function (elem){
			
			return !jQuery.expr.filters.hidden(elem);			
			
		};		
		
	}//#s10151-e10168
	
	
	//1============================================================================================	
	
	
	var r20=/%20/g,
	rbracket=/\[\]$/,
	rCRLF=/\r?\n/g,
	rhash=/#.*$/,
	rheaders=/^(.*?):[\t]*([^\r\n]*)\r?$/mg,// IE leaves an \r character at
	// EOL
	rinput=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
	// #7653, #8125, #8152: local protocol detection
	rlocalProtocol=/^(?:about|app|app\-storage|.+\-extension|file|widget):$/,
	rnoContent=/^(?:GET|HEAD)$/,
	rprotocol=/^\/\//,
	rquery=/\?/,
	rscript=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
	rselectTextarea=/^(?:select|textarea)/i,
	rspacesAjax=/\s+/,
	rts=/([?&])_=[^&]/,
	rurl=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,
	
	// Keep a copy of the old load method
	_load=jQuery.fn.load,
	
	/*
		 * Prefilters 1) They are useful to introduce custom dataTypes (see
		 * ajax/jsonp.js for an example) 2) These are called: - BEFORE asking for a
		 * transport - AFTER param serialization (s.data is a string if
		 * s.processData is true) 3) key is the dataType 4) the catchall symbol "*"
		 * can be used 5) execution will start with transport dataType and THEN
		 * continue down to "*" if needed
		 */
	prefilters={
		
	},
	
	/*
		 * Transports bindings 1) key is the dataType 2) the catchall symbol "*" can
		 * be used 3) selection will start with transport dataType and THEN go to
		 * "*" if needed
		 */
	transports={
		
	},
	
	// Document location
	ajaxLocation,
	
	// Document location segments
	ajaxLocParts;	
	
	
	//1============================================================================================	
	
	
	// #8138, IE may throw an exception when accessing
	// a field from window.location if document.domain has been set
	try{
		
		ajaxLocation=location.href;		
		
	}catch(e){
		
		// Use the href attribute of an A element
		// since IE will modify it given document.location
		ajaxLocation=document.createElement("a");		
		ajaxLocation.href="";		
		ajaxLocation=ajaxLocation.href;		
		
	}

	
	// Segment location into parts
	ajaxLocParts=rurl.exec(ajaxLocation.toLowerCase())||[];	
	
	
	//1============================================================================================	
	
	
	// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
	function addToPrefiltersOrTransports(structure){//#s10251-e10298
		
		
		// dataTypeExpression is optional and defaults to "*"
		return function (dataTypeExpression,func){
			
			
			if(typeof dataTypeExpression!=="string"){
				
				func=dataTypeExpression;				
				dataTypeExpression="*";				
				
			}

			
			if(jQuery.isFunction(func)){
				
				var dataTypes=dataTypeExpression.toLowerCase().split(rspacesAjax),
				i=0,
				length=dataTypes.length,
				dataType,
				list,
				placeBefore;				
				
				// For each dataType in the dataTypeExpression
				for(;i<length;i++){
					
					dataType=dataTypes[i];					
					// We control if we're asked to add before
					// any existing element
					placeBefore=/^\+/.test(dataType);					
					if(placeBefore){
						
						dataType=dataType.substr(1)||"*";						
						
					}

					list=structure[dataType]=structure[dataType]||[];					
					// then we add to the structure accordingly
					list[placeBefore?"unshift":"push"](func);					
					
				}
				
			}
			
		};		
		
	}//#s10251-e10298
	
	
	//1============================================================================================	

	
	// Base inspection function for prefilters and transports
	function inspectPrefiltersOrTransports(structure,options,originalOptions,jqXHR,
			dataType/* internal */,inspected/* internal */){//#s10306-e10358
		
		
		dataType=dataType||options.dataTypes[0];		
		inspected=inspected||{
			
		};		
		
		inspected[dataType]=true;		
		
		var list=structure[dataType],
		i=0,
		length=list?list.length:0,
		executeOnly=(structure===prefilters),
		selection;		
		
		for(;i<length&&(executeOnly||!selection);i++){
			
			selection=list[i](options,originalOptions,jqXHR);			
			// If we got redirected to another dataType
			// we try there if executing only and not done already
			if(typeof selection==="string"){
				
				if(!executeOnly||inspected[selection]){
					
					selection=undefined;					
					
				}else {
					
					options.dataTypes.unshift(selection);					
					selection=inspectPrefiltersOrTransports(
					structure,options,originalOptions,jqXHR,selection,inspected);					
					
				}
				
			}
			
		}

		// If we're only executing or nothing was selected
		// we try the catchall dataType if not done already
		if((executeOnly||!selection)&&!inspected["*"]){
			
			selection=inspectPrefiltersOrTransports(
			structure,options,originalOptions,jqXHR,"*",inspected);			
			
		}

		// unnecessary when only executing (prefilters)
		// but it'll be ignored by the caller in that case
		return selection;		
		
	}//#s10306-e10358
	
	
	//1============================================================================================	

	
	jQuery.fn.extend({//#s10364-e10513
		
		//载入远程 HTML 文件代码并插入至 DOM 中。注意：事件处理函数中也有一个叫 .load()方法，见#s5939-e5965处的代码
		//示例：$('#result').load('ajax/test.html', function(){alert('Load was performed.');});
		load:function (url,params,callback){//#s10798-e10901
			
			if(typeof url!=="string"&&_load){
				
				return _load.apply(this,arguments);				
				
				// Don't do a request if no elements are being requested
				
			}else if(!this.length){
				
				return this;				
				
			}

			
			var off=url.indexOf(" ");			
			if(off>=0){
				
				var selector=url.slice(off,url.length);				
				url=url.slice(0,off);				
				
			}

			
			// Default to a GET request
			var type="GET";			
			
			// If the second parameter was provided
			if(params){
				
				// If it's a function
				if(jQuery.isFunction(params)){
					
					// We assume that it's the callback
					callback=params;					
					params=undefined;					
					
					// Otherwise, build a param string
					
				}else if(typeof params==="object"){
					
					params=jQuery.param(params,jQuery.ajaxSettings.traditional);					
					type="POST";					
					
				}
				
			}

			
			var self=this;			
			
			// Request the remote document
			jQuery.ajax({
				
				url:url,
				type:type,
				dataType:"html",
				data:params,
				// Complete callback (responseText is used internally)
				complete:function (jqXHR,status,responseText){
					
					// Store the response as specified by the jqXHR object
					responseText=jqXHR.responseText;					
					// If successful, inject the HTML into all the matched elements
					if(jqXHR.isResolved()){
						
						// #4825: Get the actual response in case
						// a dataFilter is present in ajaxSettings
						jqXHR.done(function (r){
							
							responseText=r;							
							
						});						
						// See if a selector was specified
						self.html(selector?
						// Create a dummy div to hold the results
						jQuery("<div>")
						// inject the contents of the document in, removing
						// the scripts
						// to avoid any 'Permission Denied' errors in IE
						.append(responseText.replace(rscript,""))
						
						// Locate the specified elements
						.find(selector):
						
						// If not, just inject the full result
						responseText);						
						
					}

					
					if(callback){
						
						self.each(callback,[responseText,status,jqXHR]);						
						
					}
					
				}
				
			});			
			
			return this;			
			
		},
		
		//将用作提交的表单元素的值编译成字符串。
		//示例：alert($("#formId").serialize());//formId是form元素的ID
		serialize:function (){
			
			return jQuery.param(this.serializeArray());			
			
		},
		
		//将用作提交的表单元素的值编译成拥有name和value对象组成的数组。
		//示例：
		serializeArray:function (){
			
			return this.map(function (){
				
				return this.elements?jQuery.makeArray(this.elements):this;				
				
			})
			.filter(function (){
				
				return this.name&&!this.disabled&&
				(this.checked||rselectTextarea.test(this.nodeName)||
				rinput.test(this.type));				
				
			})
			.map(function (i,elem){
				
				var val=jQuery(this).val();				
				
				return val==null?
				null:
				jQuery.isArray(val)?
				jQuery.map(val,function (val,i){
					
					return {
						name:elem.name,value:val.replace(rCRLF,"\r\n")
					};					
					
				}):
				{
					name:elem.name,value:val.replace(rCRLF,"\r\n")
				};				
				
			}).get();			
			
		}
		
	});	//#s10364-e10513
	
	
	//1============================================================================================	
	

	/**
	 * 这里为jQuery增加多个与Ajax相关非常有用的方法：
	 * (1)ajaxStart方法：在AJAX 请求刚开始时执行一个处理函数。 这是一个 Ajax 事件。
	 * (2)ajaxStop方法：在Ajax请求停止后，jQuery就会触发ajaxStop事件。
	 * (3)ajaxComplete方法：为Ajax请求完成后注册一个回调函数。这是一个 Ajax 事件。每当一个Ajax请求完成，jQuery就会触发ajaxComplete事件
	 * (4)ajaxError方法：为Ajax请求出错时注册一个回调处理函数，这是一个 Ajax 事件。每当一个Ajax请求出错时，jQuery就会触发ajaxError事件
	 * (5)ajaxSuccess方法：为一个Ajax请求成功完成时显示一个信息。这是一个 Ajax 事件。每当一个Ajax请求成功完成，jQuery就会触发ajaxSuccess事件
	 * (6)ajaxSend方法：每当一个Ajax请求即将发送，jQuery就会触发ajaxSend事件。
	 */
	// Attach a bunch of functions for handling common AJAX events
	jQuery.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function (i,o){
		
		jQuery.fn[o]=function (f){
			
			return this.bind(o,f);
			
		};		
		
	});	
	
	
	//1============================================================================================	
	

	/**
	 * 这里为jQuery增加多个与Ajax相关非常有用的方法：
	 * (1)get方法：通过服务器HTTP GET请求加载数据。
	 * (2)post方法：通过服务器HTTP POST请求加载数据。
	 */
	jQuery.each(["get","post"],function (i,method){//#s10534-e10560
		
		jQuery[method]=function (url,data,callback,type){
			
			// shift arguments if data argument was omitted
			if(jQuery.isFunction(data)){
				
				type=type||callback;				
				callback=data;				
				data=undefined;				
				
			}

			
			return jQuery.ajax({
				
				type:method,
				url:url,
				data:data,
				success:callback,
				dataType:type
				
			});			
			
		};		
		
	});	//#s10534-e10560
	
	
	//1============================================================================================	
	
	
	jQuery.extend({//#s10566-e11286
		
		//通过 HTTP GET 请求从服务器载入并执行一个 JavaScript 文件
		getScript:function (url,callback){
			
			return jQuery.get(url,undefined,callback,"script");			
			
		},
		
		//通过 HTTP GET 请求从服务器载入 JSON 数据。
		getJSON:function (url,data,callback){
			
			return jQuery.get(url,data,callback,"json");			
			
		},
		
		// Creates a full fledged settings object into target
		// with both ajaxSettings and settings fields.
		// If target is omitted, writes into ajaxSettings.
		//设置未来（可以理解为全局）的 AJAX请求默认选项。
		ajaxSetup:function (target,settings){
			
			if(!settings){
				
				// Only one parameter, we extend ajaxSettings
				settings=target;				
				target=jQuery.extend(true,jQuery.ajaxSettings,settings);				
				
			}else {
				
				// target was provided, we extend into it
				jQuery.extend(true,target,jQuery.ajaxSettings,settings);				
				
			}

			// Flatten fields we don't want deep extended
			for(var field in {
				context:1,url:1
			}){
				
				if(field in settings){
					
					target[field]=settings[field];					
					
				}else if(field in jQuery.ajaxSettings){
					
					target[field]=jQuery.ajaxSettings[field];					
					
				}
				
			}

			return target;			
			
		},
		
		ajaxSettings:{
			
			url:ajaxLocation,
			isLocal:rlocalProtocol.test(ajaxLocParts[1]),
			global:true,
			type:"GET",
			contentType:"application/x-www-form-urlencoded",
			processData:true,
			async:true,
			/*
					 * timeout: 0, data: null, dataType: null, username: null, password:
					 * null, cache: null, traditional: false, headers: {},
					 */
			
			accepts:{
				
				xml:"application/xml, text/xml",
				html:"text/html",
				text:"text/plain",
				json:"application/json, text/javascript",
				"*":"*/*"
				
			},
			
			contents:{
				
				xml:/xml/,
				html:/html/,
				json:/json/
				
			},
			
			responseFields:{
				
				xml:"responseXML",
				text:"responseText"
				
			},
			
			// List of data converters
			// 1) key format is "source_type destination_type" (a single space
			// in-between)
			// 2) the catchall symbol "*" can be used for source_type
			converters:{
				
				
				// Convert anything to text
				"* text":window.String,
				
				// Text to html (true = no transformation)
				"text html":true,
				
				// Evaluate text as a json expression
				"text json":jQuery.parseJSON,
				
				// Parse text as xml
				"text xml":jQuery.parseXML
				
			}
			
		},
		
		ajaxPrefilter:addToPrefiltersOrTransports(prefilters),
		ajaxTransport:addToPrefiltersOrTransports(transports),
		
		// Main method
		/**
		 * Ajax请求的主要关键方法：
		 * 执行一个异步的HTTP（Ajax）的请求。
		 * 很多其他的Ajax请求方法都是扩展或继承于这个方法
		 */
		ajax:function (url,options){//#s11143-e111690
			
			
			// If url is an object, simulate pre-1.5 signature
			if(typeof url==="object"){
				
				options=url;				
				url=undefined;				
				
			}

			
			// Force options to be an object
			options=options||{
				
			};			
			
			var // Create the final options object
			s=jQuery.ajaxSetup({
				
			},options),
			// Callbacks context
			callbackContext=s.context||s,
			// Context for global events
			// It's the callbackContext if one was provided in the options
			// and if it's a DOM node or a jQuery collection
			globalEventContext=callbackContext!==s&&
			(callbackContext.nodeType||callbackContext instanceof jQuery)?
			jQuery(callbackContext):jQuery.event,
			// Deferreds
			deferred=jQuery.Deferred(),
			completeDeferred=jQuery._Deferred(),
			// Status-dependent callbacks
			statusCode=s.statusCode||{
				
			},
			// ifModified key
			ifModifiedKey,
			// Headers (they are sent all at once)
			requestHeaders={
				
			},
			requestHeadersNames={
				
			},
			// Response headers
			responseHeadersString,
			responseHeaders,
			// transport
			transport,
			// timeout handle
			timeoutTimer,
			// Cross-domain detection vars
			parts,
			// The jqXHR state
			state=0,
			// To know if global events are to be dispatched
			fireGlobals,
			// Loop variable
			i,
			// Fake xhr
			jqXHR={
				
				
				readyState:0,
				
				// Caches the header
				setRequestHeader:function (name,value){
					
					if(!state){
						
						var lname=name.toLowerCase();						
						name=requestHeadersNames[lname]=requestHeadersNames[lname]||name;						
						requestHeaders[name]=value;						
						
					}

					return this;					
					
				},
				
				// Raw string
				getAllResponseHeaders:function (){
					
					return state===2?responseHeadersString:null;					
					
				},
				
				// Builds headers hashtable if needed
				getResponseHeader:function (key){
					
					var match;					
					if(state===2){
						
						if(!responseHeaders){
							
							responseHeaders={
								
							};							
							while((match=rheaders.exec(responseHeadersString))){
								
								responseHeaders[match[1].toLowerCase()]=match[2];								
								
							}
							
						}

						match=responseHeaders[key.toLowerCase()];						
						
					}

					return match===undefined?null:match;					
					
				},
				
				// Overrides response content-type header
				overrideMimeType:function (type){
					
					if(!state){
						
						s.mimeType=type;						
						
					}

					return this;					
					
				},
				
				// Cancel the request
				abort:function (statusText){
					
					statusText=statusText||"abort";					
					if(transport){
						
						transport.abort(statusText);						
						
					}

					done(0,statusText);					
					return this;					
					
				}
				
			};			
			
			// Callback for when everything is done
			// It is defined here because jslint complains if it is declared
			// at the end of the function (which would be more logical and readable)
			function done(status,statusText,responses,headers){
				
				
				// Called once
				if(state===2){
					
					return ;					
					
				}

				
				// State is "done" now
				state=2;				
				
				// Clear timeout if it exists
				if(timeoutTimer){
					
					clearTimeout(timeoutTimer);					
					
				}

				
				// Dereference transport for early garbage collection
				// (no matter how long the jqXHR object will be used)
				transport=undefined;				
				
				// Cache response headers
				responseHeadersString=headers||"";				
				
				// Set readyState
				jqXHR.readyState=status?4:0;				
				
				var isSuccess,
				success,
				error,
				response=responses?ajaxHandleResponses(s,jqXHR,responses):undefined,
				lastModified,
				etag;				
				
				// If successful, handle type chaining
				if(status>=200&&status<300||status===304){
					
					
					// Set the If-Modified-Since and/or If-None-Match header, if in
					// ifModified mode.
					if(s.ifModified){
						
						
						if((lastModified=jqXHR.getResponseHeader("Last-Modified"))){
							
							jQuery.lastModified[ifModifiedKey]=lastModified;							
							
						}

						if((etag=jqXHR.getResponseHeader("Etag"))){
							
							jQuery.etag[ifModifiedKey]=etag;							
							
						}
						
					}

					
					// If not modified
					if(status===304){
						
						
						statusText="notmodified";						
						isSuccess=true;						
						
						// If we have data
						
					}else {
						
						
						try{
							
							success=ajaxConvert(s,response);							
							statusText="success";							
							isSuccess=true;							
							
						}catch(e){
							
							// We have a parsererror
							statusText="parsererror";							
							error=e;							
							
						}
						
					}
					
				}else {
					
					// We extract error from statusText
					// then normalize statusText and status for non-aborts
					error=statusText;					
					if(!statusText||status){
						
						statusText="error";						
						if(status<0){
							
							status=0;							
							
						}
						
					}
					
				}

				
				// Set data for the fake xhr object
				jqXHR.status=status;				
				jqXHR.statusText=statusText;				
				
				// Success/Error
				if(isSuccess){
					
					deferred.resolveWith(callbackContext,[success,statusText,jqXHR]);					
					
				}else {
					
					deferred.rejectWith(callbackContext,[jqXHR,statusText,error]);					
					
				}

				
				// Status-dependent callbacks
				jqXHR.statusCode(statusCode);				
				statusCode=undefined;				
				
				if(fireGlobals){
					
					globalEventContext.trigger("ajax"+(isSuccess?"Success":"Error"),
					[jqXHR,s,isSuccess?success:error]);					
					
				}

				
				// Complete
				completeDeferred.resolveWith(callbackContext,[jqXHR,statusText]);				
				
				if(fireGlobals){
					
					globalEventContext.trigger("ajaxComplete",[jqXHR,s]);					
					// Handle the global AJAX counter
					if(!(--jQuery.active)){
						
						jQuery.event.trigger("ajaxStop");						
						
					}
					
				}
				
			}

			
			// Attach deferreds
			deferred.promise(jqXHR);			
			jqXHR.success=jqXHR.done;			
			jqXHR.error=jqXHR.fail;			
			jqXHR.complete=completeDeferred.done;			
			
			// Status-dependent callbacks
			jqXHR.statusCode=function (map){
				
				if(map){
					
					var tmp;					
					if(state<2){
						
						for(tmp in map){
							
							statusCode[tmp]=[statusCode[tmp],map[tmp]];							
							
						}
						
					}else {
						
						tmp=map[jqXHR.status];						
						jqXHR.then(tmp,tmp);						
						
					}
					
				}

				return this;				
				
			};			
			
			// Remove hash character (#7531: and string promotion)
			// Add protocol if not provided (#5866: IE7 issue with protocol-less
			// urls)
			// We also use the url parameter if available
			s.url=((url||s.url)+"").replace(rhash,"").replace(rprotocol,ajaxLocParts[1]+"//");			
			
			// Extract dataTypes list
			s.dataTypes=jQuery.trim(s.dataType||"*").toLowerCase().split(rspacesAjax);			
			
			// Determine if a cross-domain request is in order
			if(s.crossDomain==null){
				
				parts=rurl.exec(s.url.toLowerCase());				
				s.crossDomain=!!(parts&&
				(parts[1]!=ajaxLocParts[1]||parts[2]!=ajaxLocParts[2]||
				(parts[3]||(parts[1]==="http:"?80:443))!=
				(ajaxLocParts[3]||(ajaxLocParts[1]==="http:"?80:443)))
				);				
				
			}

			
			// Convert data if not already a string
			if(s.data&&s.processData&&typeof s.data!=="string"){
				
				s.data=jQuery.param(s.data,s.traditional);				
				
			}

			
			// Apply prefilters
			inspectPrefiltersOrTransports(prefilters,s,options,jqXHR);			
			
			// If request was aborted inside a prefiler, stop there
			if(state===2){
				
				return false;				
				
			}

			
			// We can fire global events as of now if asked to
			fireGlobals=s.global;			
			
			// Uppercase the type
			s.type=s.type.toUpperCase();			
			
			// Determine if request has content
			s.hasContent=!rnoContent.test(s.type);			
			
			// Watch for a new set of requests
			if(fireGlobals&&jQuery.active++===0){
				
				jQuery.event.trigger("ajaxStart");				
				
			}

			
			// More options handling for requests with no content
			if(!s.hasContent){
				
				
				// If data is available, append data to url
				if(s.data){
					
					s.url+=(rquery.test(s.url)?"&":"?")+s.data;					
					
				}

				
				// Get ifModifiedKey before adding the anti-cache parameter
				ifModifiedKey=s.url;				
				
				// Add anti-cache in url if needed
				if(s.cache===false){
					
					
					var ts=jQuery.now(),
					// try replacing _= if it is there
					ret=s.url.replace(rts,"$1_="+ts);					
					
					// if nothing was replaced, add timestamp to the end
					s.url=ret+((ret===s.url)?(rquery.test(s.url)?"&":"?")+"_="+ts:"");					
					
				}
				
			}

			
			// Set the correct header, if data is being sent
			if(s.data&&s.hasContent&&s.contentType!==false||options.contentType){
				
				jqXHR.setRequestHeader("Content-Type",s.contentType);				
				
			}

			
			// Set the If-Modified-Since and/or If-None-Match header, if in
			// ifModified mode.
			if(s.ifModified){
				
				ifModifiedKey=ifModifiedKey||s.url;				
				if(jQuery.lastModified[ifModifiedKey]){
					
					jqXHR.setRequestHeader("If-Modified-Since",jQuery.lastModified[ifModifiedKey]);					
					
				}

				if(jQuery.etag[ifModifiedKey]){
					
					jqXHR.setRequestHeader("If-None-Match",jQuery.etag[ifModifiedKey]);					
					
				}
				
			}

			
			// Set the Accepts header for the server, depending on the dataType
			jqXHR.setRequestHeader(
			"Accept",
			s.dataTypes[0]&&s.accepts[s.dataTypes[0]]?
			s.accepts[s.dataTypes[0]]+(s.dataTypes[0]!=="*"?", */*; q=0.01":""):
			s.accepts["*"]
			);			
			
			// Check for headers option
			for(i in s.headers){
				
				jqXHR.setRequestHeader(i,s.headers[i]);				
				
			}

			
			// Allow custom headers/mimetypes and early abort
			if(s.beforeSend&&(s.beforeSend.call(callbackContext,jqXHR,s)===false||state===2)){
				
				// Abort if not done already
				jqXHR.abort();				
				return false;				
				
				
			}

			
			// Install callbacks on deferreds
			for(i in {
				success:1,error:1,complete:1
			}){
				
				jqXHR[i](s[i]);				
				
			}

			
			// Get transport
			transport=inspectPrefiltersOrTransports(transports,s,options,jqXHR);			
			
			// If no transport, we auto-abort
			if(!transport){
				
				done(-1,"No Transport");				
				
			}else {
				
				jqXHR.readyState=1;				
				// Send global event
				if(fireGlobals){
					
					globalEventContext.trigger("ajaxSend",[jqXHR,s]);					
					
				}

				// Timeout
				if(s.async&&s.timeout>0){
					
					timeoutTimer=setTimeout(function (){
						
						jqXHR.abort("timeout");						
						
					},s.timeout);					
					
				}

				
				try{
					
					state=1;					
					transport.send(requestHeaders,done);					
					
				}catch(e){
					
					// Propagate exception as error if not done
					if(status<2){
						
						done(-1,e);						
						// Simply rethrow otherwise
						
					}else {
						
						jQuery.error(e);						
						
					}
					
				}
				
			}

			
			return jqXHR;			
			
		},//#s11143-e111690
		
		// Serialize an array of form elements or a set of
		// key/values into a query string
		//创建一个序列化的数组或对象，适用于一个URL 地址查询字符串或Ajax请求。
		//示例：$.param({ a: [2,3,4] }) // "a=2&a=3&a=4"
		param:function (a,traditional){
			
			var s=[],
			add=function (key,value){
				
				// If value is a function, invoke it and return its value
				value=jQuery.isFunction(value)?value():value;				
				s[s.length]=encodeURIComponent(key)+"="+encodeURIComponent(value);				
				
			};			
			
			// Set traditional to true for jQuery <= 1.3.2 behavior.
			if(traditional===undefined){
				
				traditional=jQuery.ajaxSettings.traditional;				
				
			}

			
			// If an array was passed in, assume that it is an array of form
			// elements.
			if(jQuery.isArray(a)||(a.jquery&&!jQuery.isPlainObject(a))){
				
				// Serialize the form elements
				jQuery.each(a,function (){
					
					add(this.name,this.value);					
					
				});				
				
				
			}else {
				
				// If traditional, encode the "old" way (the way 1.3.2 or older
				// did it), otherwise encode params recursively.
				for(var prefix in a){
					
					buildParams(prefix,a[prefix],traditional,add);					
					
				}
				
			}

			
			// Return the resulting serialization
			return s.join("&").replace(r20,"+");			
			
		}
		
	});	//#s10566-e11286
	
	
	//1============================================================================================	
	
	
	function buildParams(prefix,obj,traditional,add){//#s11292-e11338
		
		if(jQuery.isArray(obj)){
			
			// Serialize array item.
			jQuery.each(obj,function (i,v){
				
				if(traditional||rbracket.test(prefix)){
					
					// Treat each array item as a scalar.
					add(prefix,v);					
					
					
				}else {
					
					// If array item is non-scalar (array or object), encode its
					// numeric index to resolve deserialization ambiguity issues.
					// Note that rack (as of 1.0.0) can't currently deserialize
					// nested arrays properly, and attempting to do so may cause
					// a server error. Possible fixes are to modify rack's
					// deserialization algorithm or to provide an option or flag
					// to force array serialization to be shallow.
					buildParams(prefix+"["+(typeof v==="object"||jQuery.isArray(v)?i:"")+"]",v,traditional,add);					
					
				}
				
			});			
			
			
		}else if(!traditional&&obj!=null&&typeof obj==="object"){
			
			// Serialize object item.
			for(var name in obj){
				
				buildParams(prefix+"["+name+"]",obj[name],traditional,add);				
				
			}
			
			
		}else {
			
			// Serialize scalar item.
			add(prefix,obj);			
			
		}
		
	}//#s11292-e11338
	
	
	//1============================================================================================	

	
	// This is still on the jQuery object... for now
	// Want to move this to jQuery.ajax some day
	jQuery.extend({//#s11346-e11361
		
		
		// Counter for holding the number of active queries
		active:0,
		
		// Last-Modified header cache for next request
		lastModified:{
			
		},
		etag:{
			
		}
		
		
	});	//#s11346-e11361
	
	
	//1============================================================================================	
	
	
	/*
	 * Handles responses to an ajax request: - sets all responseXXX fields
	 * accordingly - finds the right dataType (mediates between content-type and
	 * expected dataType) - returns the corresponding response
	 */
	function ajaxHandleResponses(s,jqXHR,responses){//#s11372-e11471
		
		
		var contents=s.contents,
		dataTypes=s.dataTypes,
		responseFields=s.responseFields,
		ct,
		type,
		finalDataType,
		firstDataType;		
		
		// Fill responseXXX fields
		for(type in responseFields){
			
			if(type in responses){
				
				jqXHR[responseFields[type]]=responses[type];				
				
			}
			
		}

		
		// Remove auto dataType and get content-type in the process
		while(dataTypes[0]==="*"){
			
			dataTypes.shift();			
			if(ct===undefined){
				
				ct=s.mimeType||jqXHR.getResponseHeader("content-type");				
				
			}
			
		}

		
		// Check if we're dealing with a known content-type
		if(ct){
			
			for(type in contents){
				
				if(contents[type]&&contents[type].test(ct)){
					
					dataTypes.unshift(type);					
					break;					
					
				}
				
			}
			
		}

		
		// Check to see if we have a response for the expected dataType
		if(dataTypes[0] in responses){
			
			finalDataType=dataTypes[0];			
			
		}else {
			
			// Try convertible dataTypes
			for(type in responses){
				
				if(!dataTypes[0]||s.converters[type+" "+dataTypes[0]]){
					
					finalDataType=type;					
					break;					
					
				}

				if(!firstDataType){
					
					firstDataType=type;					
					
				}
				
			}

			// Or just use first one
			finalDataType=finalDataType||firstDataType;			
			
		}

		
		// If we found a dataType
		// We add the dataType to the list if needed
		// and return the corresponding response
		if(finalDataType){
			
			if(finalDataType!==dataTypes[0]){
				
				dataTypes.unshift(finalDataType);				
				
			}

			return responses[finalDataType];			
			
		}
		
	}//#s11372-e11471
	
	
	//1============================================================================================	

	
	// Chain conversions given the request and the original response
	function ajaxConvert(s,response){//#s11478-e11600
		
		
		// Apply the dataFilter if provided
		if(s.dataFilter){
			
			response=s.dataFilter(response,s.dataType);			
			
		}

		
		var dataTypes=s.dataTypes,
		converters={
			
		},
		i,
		key,
		length=dataTypes.length,
		tmp,
		// Current and previous dataTypes
		current=dataTypes[0],
		prev,
		// Conversion expression
		conversion,
		// Conversion function
		conv,
		// Conversion functions (transitive conversion)
		conv1,
		conv2;		
		
		// For each dataType in the chain
		for(i=1;i<length;i++){
			
			
			// Create converters map
			// with lowercased keys
			if(i===1){
				
				for(key in s.converters){
					
					if(typeof key==="string"){
						
						converters[key.toLowerCase()]=s.converters[key];						
						
					}
					
				}
				
			}

			
			// Get the dataTypes
			prev=current;			
			current=dataTypes[i];			
			
			// If current is auto dataType, update it to prev
			if(current==="*"){
				
				current=prev;				
				// If no auto and dataTypes are actually different
				
			}else if(prev!=="*"&&prev!==current){
				
				
				// Get the converter
				conversion=prev+" "+current;				
				conv=converters[conversion]||converters["* "+current];				
				
				// If there is no direct converter, search transitively
				if(!conv){
					
					conv2=undefined;					
					for(conv1 in converters){
						
						tmp=conv1.split(" ");						
						if(tmp[0]===prev||tmp[0]==="*"){
							
							conv2=converters[tmp[1]+" "+current];							
							if(conv2){
								
								conv1=converters[conv1];								
								if(conv1===true){
									
									conv=conv2;									
									
								}else if(conv2===true){
									
									conv=conv1;									
									
								}

								break;								
								
							}
							
						}
						
					}
					
				}

				// If we found no converter, dispatch an error
				if(!(conv||conv2)){
					
					jQuery.error("No conversion from "+conversion.replace(" "," to "));					
					
				}

				// If found converter is not an equivalence
				if(conv!==true){
					
					// Convert with 1 or 2 converters accordingly
					response=conv?conv(response):conv2(conv1(response));					
					
				}
				
			}
			
		}

		return response;		
		
	}//#s11478-e11600
	
	
	//1============================================================================================	
	
	
	var jsc=jQuery.now(),
	jsre=/(\=)\?(&|$)|\?\?/i;
	
	
	//1============================================================================================	
	
	
	// Default jsonp settings
	jQuery.ajaxSetup({
		
		jsonp:"callback",
		jsonpCallback:function (){
			
			return jQuery.expando+"_"+(jsc++);			
			
		}
		
	});	
	
	
	//1============================================================================================	
	
	
	// Detect, normalize options and install callbacks for jsonp requests
	jQuery.ajaxPrefilter("json jsonp",function (s,originalSettings,jqXHR){//#s11630-e11717
		
		
		var inspectData=s.contentType==="application/x-www-form-urlencoded"&&
		(typeof s.data==="string");		
		
		if(s.dataTypes[0]==="jsonp"||
		s.jsonp!==false&&(jsre.test(s.url)||
		inspectData&&jsre.test(s.data))){
			
			
			var responseContainer,
			jsonpCallback=s.jsonpCallback=
			jQuery.isFunction(s.jsonpCallback)?s.jsonpCallback():s.jsonpCallback,
			previous=window[jsonpCallback],
			url=s.url,
			data=s.data,
			replace="$1"+jsonpCallback+"$2";			
			
			if(s.jsonp!==false){
				
				url=url.replace(jsre,replace);				
				if(s.url===url){
					
					if(inspectData){
						
						data=data.replace(jsre,replace);						
						
					}

					if(s.data===data){
						
						// Add callback manually
						url+=(/\?/.test(url)?"&":"?")+s.jsonp+"="+jsonpCallback;						
						
					}
					
				}
				
			}

			
			s.url=url;			
			s.data=data;			
			
			// Install callback
			window[jsonpCallback]=function (response){
				
				responseContainer=[response];				
				
			};			
			
			// Clean-up function
			jqXHR.always(function (){
				
				// Set callback back to previous value
				window[jsonpCallback]=previous;				
				// Call if it was a function and we have a response
				if(responseContainer&&jQuery.isFunction(previous)){
					
					window[jsonpCallback](responseContainer[0]);					
					
				}
				
			});			
			
			// Use data converter to retrieve json after script execution
			s.converters["script json"]=function (){
				
				if(!responseContainer){
					
					jQuery.error(jsonpCallback+" was not called");					
					
				}

				return responseContainer[0];				
				
			};			
			
			// force json dataType
			s.dataTypes[0]="json";			
			
			// Delegate to script
			return "script";			
			
		}
		
	});	//#s11630-e11717
	
	
	//1============================================================================================	
	
	
	// Install script dataType
	jQuery.ajaxSetup({//#s11724-e11747
		
		accepts:{
			
			script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
			
		},
		contents:{
			
			script:/javascript|ecmascript/
			
		},
		converters:{
			
			"text script":function (text){
				
				jQuery.globalEval(text);				
				return text;				
				
			}
			
		}
		
	});	//#s11724-e11747
	
	
	//1============================================================================================	
	
	
	// Handle cache's special case and global
	jQuery.ajaxPrefilter("script",function (s){//#s11754-e11769
		
		if(s.cache===undefined){
			
			s.cache=false;			
			
		}

		if(s.crossDomain){
			
			s.type="GET";			
			s.global=false;			
			
		}
		
	});	//#s11754-e11769
	
	
	//1============================================================================================	
	
	
	// Bind script tag hack transport
	jQuery.ajaxTransport("script",function (s){//#s11776-e11857
		
		
		// This transport only deals with cross domain requests
		if(s.crossDomain){
			
			
			var script,
			head=document.head||document.getElementsByTagName("head")[0]||document.documentElement;			
			
			return {
				
				
				send:function (_,callback){
					
					
					script=document.createElement("script");					
					
					script.async="async";					
					
					if(s.scriptCharset){
						
						script.charset=s.scriptCharset;						
						
					}

					
					script.src=s.url;					
					
					// Attach handlers for all browsers
					script.onload=script.onreadystatechange=function (_,isAbort){
						
						
						if(isAbort||!script.readyState||/loaded|complete/.test(script.readyState)){
							
							
							// Handle memory leak in IE
							script.onload=script.onreadystatechange=null;							
							
							// Remove the script
							if(head&&script.parentNode){
								
								head.removeChild(script);								
								
							}

							
							// Dereference the script
							script=undefined;							
							
							// Callback if not abort
							if(!isAbort){
								
								callback(200,"success");								
								
							}
							
						}
						
					};					
					// Use insertBefore instead of appendChild to circumvent an IE6
					// bug.
					// This arises when a base node is used (#2709 and #4378).
					head.insertBefore(script,head.firstChild);					
					
				},
				
				abort:function (){
					
					if(script){
						
						script.onload(0,1);						
						
					}
					
				}
				
			};			
			
		}
		
	});	//#s11776-e11857
	
	
	//1============================================================================================	
	
	
	var // #5280: Internet Explorer will keep connections alive if we don't abort on
	// unload
	xhrOnUnloadAbort=window.ActiveXObject?function (){
		
		// Abort all pending requests
		for(var key in xhrCallbacks){
			
			xhrCallbacks[key](0,1);			
			
		}
		
	}
:false,
	xhrId=0,
	xhrCallbacks;	
	
	
	//1============================================================================================	
	
	
	// Functions to create xhrs
	function createStandardXHR(){
		
		try{
			
			return new window.XMLHttpRequest();			
			
		}catch(e){
			
		}
		
	}
	
	
	//1============================================================================================	

	
	function createActiveXHR(){
		
		try{
			
			return new window.ActiveXObject("Microsoft.XMLHTTP");			
			
		}catch(e){
			
		}
		
	}
	
	
	//1============================================================================================	

	
	// Create the request object
	// (This is still attached to ajaxSettings for backward compatibility)
	jQuery.ajaxSettings.xhr=window.ActiveXObject?
	/*
		 * Microsoft failed to properly implement the XMLHttpRequest in IE7 (can't
		 * request local files), so we use the ActiveXObject when it is available
		 * Additionally XMLHttpRequest can be disabled in IE7/IE8 so we need a
		 * fallback.
		 */
	function (){
		
		return !this.isLocal&&createStandardXHR()||createActiveXHR();		
		
	}
:
	// For all other browsers, use the standard XMLHttpRequest object
	createStandardXHR;
	
	
	//1============================================================================================	
	
	
	// Determine support properties
	(function (xhr){
		
		jQuery.extend(jQuery.support,{
			
			ajax:!!xhr,
			cors:!!xhr&&("withCredentials" in xhr)
			
		});		
		
	})(jQuery.ajaxSettings.xhr());	
	
	
	//1============================================================================================	
	
	
	// Create transport if the browser can provide an xhr
	if(jQuery.support.ajax){//#s11955-e12220
		
		
		jQuery.ajaxTransport(function (s){
			
			// Cross domain only allowed if supported through XMLHttpRequest
			if(!s.crossDomain||jQuery.support.cors){
				
				
				var callback;				
				
				return {
					
					send:function (headers,complete){
						
						
						// Get a new xhr
						var xhr=s.xhr(),
						handle,
						i;						
						
						// Open the socket
						// Passing null username, generates a login popup on Opera
						// (#2865)
						if(s.username){
							
							xhr.open(s.type,s.url,s.async,s.username,s.password);							
							
						}else {
							
							xhr.open(s.type,s.url,s.async);							
							
						}

						
						// Apply custom fields if provided
						if(s.xhrFields){
							
							for(i in s.xhrFields){
								
								xhr[i]=s.xhrFields[i];								
								
							}
							
						}

						
						// Override mime type if needed
						if(s.mimeType&&xhr.overrideMimeType){
							
							xhr.overrideMimeType(s.mimeType);							
							
						}

						
						// X-Requested-With header
						// For cross-domain requests, seeing as conditions for a
						// preflight are
						// akin to a jigsaw puzzle, we simply never set it to be
						// sure.
						// (it can always be set on a per-request basis or even
						// using ajaxSetup)
						// For same-domain requests, won't change header if already
						// provided.
						if(!s.crossDomain&&!headers["X-Requested-With"]){
							
							headers["X-Requested-With"]="XMLHttpRequest";							
							
						}

						
						// Need an extra try/catch for cross domain requests in
						// Firefox 3
						try{
							
							for(i in headers){
								
								xhr.setRequestHeader(i,headers[i]);								
								
							}
							
						}catch(_){
							
						}

						
						// Do send the request
						// This may raise an exception which is actually
						// handled in jQuery.ajax (so no try/catch here)
						xhr.send((s.hasContent&&s.data)||null);						
						
						// Listener
						callback=function (_,isAbort){
							
							
							var status,
							statusText,
							responseHeaders,
							responses,
							xml;							
							
							// Firefox throws exceptions when accessing properties
							// of an xhr when a network error occured
							// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
							try{
								
								
								// Was never called and is aborted or complete
								if(callback&&(isAbort||xhr.readyState===4)){
									
									
									// Only called once
									callback=undefined;									
									
									// Do not keep as active anymore
									if(handle){
										
										xhr.onreadystatechange=jQuery.noop;										
										if(xhrOnUnloadAbort){
											
											delete xhrCallbacks[handle];											
											
										}
										
									}

									
									// If it's an abort
									if(isAbort){
										
										// Abort it manually if needed
										if(xhr.readyState!==4){
											
											xhr.abort();											
											
										}
										
									}else {
										
										status=xhr.status;										
										responseHeaders=xhr.getAllResponseHeaders();										
										responses={
											
										};										
										xml=xhr.responseXML;										
										
										// Construct response list
										if(xml&&xml.documentElement/* #4958 */){
											
											responses.xml=xml;											
											
										}

										responses.text=xhr.responseText;										
										
										// Firefox throws an exception when
										// accessing
										// statusText for faulty cross-domain
										// requests
										try{
											
											statusText=xhr.statusText;											
											
										}catch(e){
											
											// We normalize with Webkit giving an
											// empty statusText
											statusText="";											
											
										}

										
										// Filter status for non standard behaviors
										
										// If the request is local and we have data:
										// assume a success
										// (success with no data won't get notified,
										// that's the best we
										// can do given current implementations)
										if(!status&&s.isLocal&&!s.crossDomain){
											
											status=responses.text?200:404;											
											// IE - #1450: sometimes returns 1223 when
											// it should be 204
											
										}else if(status===1223){
											
											status=204;											
											
										}
										
									}
									
								}
								
							}catch(firefoxAccessException){
								
								if(!isAbort){
									
									complete(-1,firefoxAccessException);									
									
								}
								
							}

							
							// Call complete if needed
							if(responses){
								
								complete(status,statusText,responses,responseHeaders);								
								
							}
							
						};						
						
						// if we're in sync mode or it's in cache
						// and has been retrieved directly (IE6 & IE7)
						// we need to manually fire the callback
						if(!s.async||xhr.readyState===4){
							
							callback();							
							
						}else {
							
							handle=++xhrId;							
							if(xhrOnUnloadAbort){
								
								// Create the active xhrs callbacks list if needed
								// and attach the unload handler
								if(!xhrCallbacks){
									
									xhrCallbacks={
										
									};									
									jQuery(window).unload(xhrOnUnloadAbort);									
									
								}

								// Add to list of active xhrs callbacks
								xhrCallbacks[handle]=callback;								
								
							}

							xhr.onreadystatechange=callback;							
							
						}
						
					},
					
					abort:function (){
						
						if(callback){
							
							callback(0,1);							
							
						}
						
					}
					
				};				
				
			}
			
		});		
		
	}//#s11955-e12220
	
	
	//1============================================================================================	
	
	
	var elemdisplay={
		
	},
	iframe,iframeDoc,
	rfxtypes=/^(?:toggle|show|hide)$/,
	rfxnum=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,
	timerId,
	fxAttrs=[
	// height animations
	["height","marginTop","marginBottom","paddingTop","paddingBottom"],
	// width animations
	["width","marginLeft","marginRight","paddingLeft","paddingRight"],
	// opacity animations
	["opacity"]
	],
	fxNow,
	requestAnimationFrame=window.webkitRequestAnimationFrame||
	window.mozRequestAnimationFrame||
	window.oRequestAnimationFrame;
	
	
	//1============================================================================================	
	
	
	jQuery.fn.extend({//#s12250-e12657
		
		//显示匹配的元素（可根据参数的不同有多种不同的动画显示效果）
		//示例：$("p").show();或$("p").show("slow");或$("p").show("slow",function(){alert("显示完成")});等
		show:function (speed,easing,callback){//#s12713-e12782
			
			var elem,display;			
			
			if(speed||speed===0){
				
				return this.animate(genFx("show",3),speed,easing,callback);				
				
				
			}else {
				
				for(var i=0,j=this.length;i<j;i++){
					
					elem=this[i];					
					
					if(elem.style){
						
						display=elem.style.display;						
						
						// Reset the inline display of this element to learn if it
						// is
						// being hidden by cascaded rules or not
						if(!jQuery._data(elem,"olddisplay")&&display==="none"){
							
							display=elem.style.display="";							
							
						}

						
						// Set elements which have been overridden with display:
						// none
						// in a stylesheet to whatever the default browser style is
						// for such an element
						if(display===""&&jQuery.css(elem,"display")==="none"){
							
							jQuery._data(elem,"olddisplay",defaultDisplay(elem.nodeName));							
							
						}
						
					}
					
				}

				
				// Set the display of most of the elements in a second loop
				// to avoid the constant reflow
				for(i=0;i<j;i++){
					
					elem=this[i];					
					
					if(elem.style){
						
						display=elem.style.display;						
						
						if(display===""||display==="none"){
							
							elem.style.display=jQuery._data(elem,"olddisplay")||"";							
							
						}
						
					}
					
				}

				
				return this;				
				
			}
			
		},//#s12713-e12782

		//隐藏匹配的元素（可根据参数的不同有多种不同的动画隐藏效果）
		//示例：$("p").hide();或$("p").hide("slow");或$("p").hide("slow",function(){alert("隐藏完成")});等
		hide:function (speed,easing,callback){
			
			if(speed||speed===0){
				
				return this.animate(genFx("hide",3),speed,easing,callback);				
				
				
			}else {
				
				for(var i=0,j=this.length;i<j;i++){
					
					if(this[i].style){
						
						var display=jQuery.css(this[i],"display");						
						
						if(display!=="none"&&!jQuery._data(this[i],"olddisplay")){
							
							jQuery._data(this[i],"olddisplay",display);							
							
						}
						
					}
					
				}

				
				// Set the display of the elements in a second loop
				// to avoid the constant reflow
				for(i=0;i<j;i++){
					
					if(this[i].style){
						
						this[i].style.display="none";						
						
					}
					
				}

				
				return this;				
				
			}
			
		},
		
		// Save the old toggle function
		_toggle:jQuery.fn.toggle,
		
		//交替切换显示或隐藏匹配的元素（可根据参数的不同有多种不同的动画效果）
		//示例：$("p").toggle();或$("p").toggle("slow");或$("p").toggle("slow",function(){alert("切换显示和隐藏完成")});等
		toggle:function (fn,fn2,callback){
			
			var bool=typeof fn==="boolean";			
			
			if(jQuery.isFunction(fn)&&jQuery.isFunction(fn2)){
				
				this._toggle.apply(this,arguments);				
				
				
			}else if(fn==null||bool){
				
				this.each(function (){
					
					var state=bool?fn:jQuery(this).is(":hidden");					
					jQuery(this)[state?"show":"hide"]();					
					
				});				
				
				
			}else {
				
				this.animate(genFx("toggle",3),fn,fn2,callback);				
				
			}

			
			return this;			
			
		},
		
		//调整匹配元素的透明度。
		//示例： 
		//(1)先在body中添加<img id="book" src="book.png" alt="" width="100" height="123" />
		//(2)执行：$('#book').fadeTo('slow', 0.5, function(){});
		fadeTo:function (speed,to,easing,callback){
			
			return this.filter(":hidden").css("opacity",0).show().end()
			.animate({
				opacity:to
			},speed,easing,callback);			
			
		},
		
		//执行一个CSS属性设置的自定义动画。
		animate:function (prop,speed,easing,callback){//#s12880-e13073
			
			var optall=jQuery.speed(speed,easing,callback);			
			
			if(jQuery.isEmptyObject(prop)){
				
				return this.each(optall.complete,[false]);				
				
			}

			
			// Do not change referenced properties as per-property easing will be
			// lost
			prop=jQuery.extend({
				
			},prop);			
			
			return this[optall.queue===false?"each":"queue"](function (){
				
				// XXX 'this' does not always have a nodeName when running the
				// test suite
				
				if(optall.queue===false){
					
					jQuery._mark(this);					
					
				}

				
				var opt=jQuery.extend({
					
				},optall),
				isElement=this.nodeType===1,
				hidden=isElement&&jQuery(this).is(":hidden"),
				name,val,p,
				display,e,
				parts,start,end,unit;				
				
				// will store per property easing and be used to determine when an
				// animation is complete
				opt.animatedProperties={
					
				};				
				
				for(p in prop){
					
					
					// property name normalization
					name=jQuery.camelCase(p);					
					if(p!==name){
						
						prop[name]=prop[p];						
						delete prop[p];						
						
					}

					
					val=prop[name];					
					
					// easing resolution: per property > opt.specialEasing >
					// opt.easing > 'swing' (default)
					if(jQuery.isArray(val)){
						
						opt.animatedProperties[name]=val[1];						
						val=prop[name]=val[0];						
						
					}else {
						
						opt.animatedProperties[name]=opt.specialEasing&&opt.specialEasing[name]||opt.easing||'swing';						
						
					}

					
					if(val==="hide"&&hidden||val==="show"&&!hidden){
						
						return opt.complete.call(this);						
						
					}

					
					if(isElement&&(name==="height"||name==="width")){
						
						// Make sure that nothing sneaks out
						// Record all 3 overflow attributes because IE does not
						// change the overflow attribute when overflowX and
						// overflowY are set to the same value
						opt.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY];						
						
						// Set display property to inline-block for height/width
						// animations on inline elements that are having
						// width/height
						// animated
						if(jQuery.css(this,"display")==="inline"&&
						jQuery.css(this,"float")==="none"){
							
							if(!jQuery.support.inlineBlockNeedsLayout){
								
								this.style.display="inline-block";								
								
								
							}else {
								
								display=defaultDisplay(this.nodeName);								
								
								// inline-level elements accept inline-block;
								// block-level elements need to be inline with
								// layout
								if(display==="inline"){
									
									this.style.display="inline-block";									
									
									
								}else {
									
									this.style.display="inline";									
									this.style.zoom=1;									
									
								}
								
							}
							
						}
						
					}
					
				}

				
				if(opt.overflow!=null){
					
					this.style.overflow="hidden";					
					
				}

				
				for(p in prop){
					
					e=new jQuery.fx(this,opt,p);					
					val=prop[p];					
					
					if(rfxtypes.test(val)){
						
						e[val==="toggle"?hidden?"show":"hide":val]();						
						
						
					}else {
						
						parts=rfxnum.exec(val);						
						start=e.cur();						
						
						if(parts){
							
							end=parseFloat(parts[2]);							
							unit=parts[3]||(jQuery.cssNumber[p]?"":"px");							
							
							// We need to compute starting value
							if(unit!=="px"){
								
								jQuery.style(this,p,(end||1)+unit);								
								start=((end||1)/e.cur())*start;								
								jQuery.style(this,p,start+unit);								
								
							}

							
							// If a +=/-= token was provided, we're doing a relative
							// animation
							if(parts[1]){
								
								end=((parts[1]==="-="?-1:1)*end)+start;								
								
							}

							
							e.custom(start,end,unit);							
							
							
						}else {
							
							e.custom(start,val,"");							
							
						}
						
					}
					
				}

				
				// For JS strict compliance
				return true;				
				
			});			
			
		},//#s12880-e13073
		
		//停止匹配元素当前正在运行的动画。
		stop:function (clearQueue,gotoEnd){//#s13076-e13125
			
			if(clearQueue){
				
				this.queue([]);				
				
			}

			
			this.each(function (){
				
				var timers=jQuery.timers,
				i=timers.length;				
				// clear marker counters if we know they won't be
				if(!gotoEnd){
					
					jQuery._unmark(true,this);					
					
				}
				while(i--){
					
					if(timers[i].elem===this){
						
						if(gotoEnd){
							
							// force the next step to be the last
							timers[i](true);							
							
						}

						
						timers.splice(i,1);						
						
					}
					
				}
				
			});			
			
			// start the next in the queue if the last step wasn't forced
			if(!gotoEnd){
				
				this.dequeue();				
				
			}

			
			return this;			
			
		}//#s13076-e13125
		
		
	});//#s12250-e12657
	
	
	//1============================================================================================	
	
	
	// Animations created synchronously will run synchronously
	function createFxNow(){
		
		setTimeout(clearFxNow,0);		
		return (fxNow=jQuery.now());		
		
	}
	
	
	//1============================================================================================	

	
	function clearFxNow(){
		
		fxNow=undefined;		
		
	}
	
	
	//1============================================================================================	

	
	// Generate parameters to create a standard animation
	function genFx(type,num){//#s12686-e12700
		
		var obj={
			
		};		
		
		jQuery.each(fxAttrs.concat.apply([],fxAttrs.slice(0,num)),function (){
			
			obj[this]=type;			
			
		});		
		
		return obj;		
		
	}//#s12686-e12700
	
	
	//1============================================================================================	

	
	// Generate shortcuts for custom animations
	jQuery.each({//#s12707-e12730
		
		//用滑动动画显示一个匹配元素：向下滑动展开显示匹配的元素，类似于“向下拉开窗帘”
		//示例： 
		//(1)先在body中添加<img id="book" src="book.png" alt="" width="100" height="123" />
		//(2)执行：$('#book').slideDown('slow',function(){});
		slideDown:genFx("show",1),
		
		//用滑动动画隐藏一个匹配元素：向上滑动收起隐藏匹配的元素，类似于“向上收起窗帘”
		//示例： 
		//(1)先在body中添加<img id="book" src="book.png" alt="" width="100" height="123" />
		//(2)执行：$('#book').slideUp('slow',function(){});
		slideUp:genFx("hide",1),
		
		//用滑动动画显示或隐藏一个匹配元素：滑动动画交替切换显示和隐藏匹配的元素，相当于交替执行.slideDown()和.slideUp()方法。
		//示例： 
		//(1)先在body中添加<img id="book" src="book.png" alt="" width="100" height="123" />
		//(2)执行：$('#book').slideToggle('slow',function(){});
		slideToggle:genFx("toggle",1),
		
		//通过淡入的方式显示匹配元素。
		//示例： 
		//(1)先在body中添加<img id="book" src="book.png" alt="" width="100" height="123" />
		//(2)执行：$('#book').fadeTo('slow',function(){});
		fadeIn:{
			opacity:"show"
		},

		//通过淡出的方式隐藏匹配元素。
		//示例： 
		//(1)先在body中添加<img id="book" src="book.png" alt="" width="100" height="123" />
		//(2)执行：$('#book').fadeOut('slow',function(){});
		fadeOut:{
			opacity:"hide"
		},
		
		//交替使用淡入和淡出的方式显示和隐藏匹配的元素
		//示例： 
		//(1)先在body中添加<img id="book" src="book.png" alt="" width="100" height="123" />
		//(2)执行：$('#book').fadeToggle('slow',function(){});
		fadeToggle:{
			opacity:"toggle"
		}
		
	},function (name,props){
		
		jQuery.fn[name]=function (speed,easing,callback){
			
			return this.animate(props,speed,easing,callback);			
			
		};		
		
	});	//#s12707-e12730
	
	
	//1============================================================================================	
	
	
	jQuery.extend({//#s12736-e12811
		
		speed:function (speed,easing,fn){
			
			var opt=speed&&typeof speed==="object"?jQuery.extend({
				
			},speed):{
				
				complete:fn||!fn&&easing||
				jQuery.isFunction(speed)&&speed,
				duration:speed,
				easing:fn&&easing||easing&&!jQuery.isFunction(easing)&&easing
				
			};			
			
			opt.duration=jQuery.fx.off?0:typeof opt.duration==="number"?opt.duration:
			opt.duration in jQuery.fx.speeds?jQuery.fx.speeds[opt.duration]:jQuery.fx.speeds._default;			
			
			// Queueing
			opt.old=opt.complete;			
			opt.complete=function (noUnmark){
				
				if(jQuery.isFunction(opt.old)){
					
					opt.old.call(this);					
					
				}

				
				if(opt.queue!==false){
					
					jQuery.dequeue(this);					
					
				}else if(noUnmark!==false){
					
					jQuery._unmark(this);					
					
				}
				
			};			
			
			return opt;			
			
		},
		
		easing:{
			
			linear:function (p,n,firstNum,diff){
				
				return firstNum+diff*p;				
				
			},
			swing:function (p,n,firstNum,diff){
				
				return ((-Math.cos(p*Math.PI)/2)+0.5)*diff+firstNum;				
				
			}
			
		},
		
		timers:[],
		
		fx:function (elem,options,prop){
			
			this.options=options;			
			this.elem=elem;			
			this.prop=prop;			
			
			options.orig=options.orig||{
				
			};			
			
		}
		
		
	});	//#s12736-e12811
	
	
	//1============================================================================================	
	
	
	jQuery.fx.prototype={//#s12817-e13033
		
		// Simple function for setting a style value
		update:function (){
			
			if(this.options.step){
				
				this.options.step.call(this.elem,this.now,this);				
				
			}

			
			(jQuery.fx.step[this.prop]||jQuery.fx.step._default)(this);			
			
		},
		
		// Get the current size
		cur:function (){
			
			if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){
				
				return this.elem[this.prop];				
				
			}

			
			var parsed,
			r=jQuery.css(this.elem,this.prop);			
			// Empty strings, null, undefined and "auto" are converted to 0,
			// complex values such as "rotate(1rad)" are returned as is,
			// simple values such as "10px" are parsed to Float.
			return isNaN(parsed=parseFloat(r))?!r||r==="auto"?0:r:parsed;			
			
		},
		
		// Start an animation from one number to another
		custom:function (from,to,unit){
			
			var self=this,
			fx=jQuery.fx,
			raf;			
			
			this.startTime=fxNow||createFxNow();			
			this.start=from;			
			this.end=to;			
			this.unit=unit||this.unit||(jQuery.cssNumber[this.prop]?"":"px");			
			this.now=this.start;			
			this.pos=this.state=0;			
			
			function t(gotoEnd){
				
				return self.step(gotoEnd);				
				
			}

			
			t.elem=this.elem;			
			
			if(t()&&jQuery.timers.push(t)&&!timerId){
				
				// Use requestAnimationFrame instead of setInterval if available
				if(requestAnimationFrame){
					
					timerId=true;					
					raf=function (){
						
						// When timerId gets set to null at any point, this stops
						if(timerId){
							
							requestAnimationFrame(raf);							
							fx.tick();							
							
						}
						
					};					
					requestAnimationFrame(raf);					
					
				}else {
					
					timerId=setInterval(fx.tick,fx.interval);					
					
				}
				
			}
			
		},
		
		// Simple 'show' function
		show:function (){
			
			// Remember where we started, so that we can go back to it later
			this.options.orig[this.prop]=jQuery.style(this.elem,this.prop);			
			this.options.show=true;			
			
			// Begin the animation
			// Make sure that we start at a small width/height to avoid any
			// flash of content
			this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());			
			
			// Start by showing the element
			jQuery(this.elem).show();			
			
		},
		
		// Simple 'hide' function
		hide:function (){
			
			// Remember where we started, so that we can go back to it later
			this.options.orig[this.prop]=jQuery.style(this.elem,this.prop);			
			this.options.hide=true;			
			
			// Begin the animation
			this.custom(this.cur(),0);			
			
		},
		
		// Each step of an animation
		step:function (gotoEnd){
			
			var t=fxNow||createFxNow(),
			done=true,
			elem=this.elem,
			options=this.options,
			i,n;			
			
			if(gotoEnd||t>=options.duration+this.startTime){
				
				this.now=this.end;				
				this.pos=this.state=1;				
				this.update();				
				
				options.animatedProperties[this.prop]=true;				
				
				for(i in options.animatedProperties){
					
					if(options.animatedProperties[i]!==true){
						
						done=false;						
						
					}
					
				}

				
				if(done){
					
					// Reset the overflow
					if(options.overflow!=null&&!jQuery.support.shrinkWrapBlocks){
						
						
						jQuery.each(["","X","Y"],function (index,value){
							
							elem.style["overflow"+value]=options.overflow[index];							
							
						});						
						
					}

					
					// Hide the element if the "hide" operation was done
					if(options.hide){
						
						jQuery(elem).hide();						
						
					}

					
					// Reset the properties, if the item has been hidden or shown
					if(options.hide||options.show){
						
						for(var p in options.animatedProperties){
							
							jQuery.style(elem,p,options.orig[p]);							
							
						}
						
					}

					
					// Execute the complete function
					options.complete.call(elem);					
					
				}

				
				return false;				
				
				
			}else {
				
				// classical easing cannot be used with an Infinity duration
				if(options.duration==Infinity){
					
					this.now=t;					
					
				}else {
					
					n=t-this.startTime;					
					this.state=n/options.duration;					
					
					// Perform the easing function, defaults to swing
					this.pos=jQuery.easing[options.animatedProperties[this.prop]](this.state,n,0,1,options.duration);					
					this.now=this.start+((this.end-this.start)*this.pos);					
					
				}

				// Perform the next step of the animation
				this.update();				
				
			}

			
			return true;			
			
		}
		
	};//#s12817-e13033
	
	
	//1============================================================================================	
	
	
	jQuery.extend(jQuery.fx,{//#s13039-e13104
		
		tick:function (){
			
			for(var timers=jQuery.timers,i=0;i<timers.length;++i){
				
				if(!timers[i]()){
					
					timers.splice(i--,1);					
					
				}
				
			}

			
			if(!timers.length){
				
				jQuery.fx.stop();				
				
			}
			
		},
		
		interval:13,
		
		stop:function (){
			
			clearInterval(timerId);			
			timerId=null;			
			
		},
		
		speeds:{
			
			slow:600,
			fast:200,
			// Default speed
			_default:400
			
		},
		
		step:{
			
			opacity:function (fx){
				
				jQuery.style(fx.elem,"opacity",fx.now);				
				
			},
			
			_default:function (fx){
				
				if(fx.elem.style&&fx.elem.style[fx.prop]!=null){
					
					fx.elem.style[fx.prop]=(fx.prop==="width"||fx.prop==="height"?Math.max(0,fx.now):fx.now)+fx.unit;					
					
				}else {
					
					fx.elem[fx.prop]=fx.now;					
					
				}
				
			}
			
		}
		
	});//#s13039-e13104	
	
	
	//1============================================================================================	
	
	
	if(jQuery.expr&&jQuery.expr.filters){//#s13110-e13122
		
		jQuery.expr.filters.animated=function (elem){
			
			return jQuery.grep(jQuery.timers,function (fn){
				
				return elem===fn.elem;				
				
			}).length;			
			
		};		
		
	}//#s13110-e13122
	
	
	//1============================================================================================	

	
	// Try to restore the default display value of an element
	function defaultDisplay(nodeName){//#s13129-e13189
		
		
		if(!elemdisplay[nodeName]){
			
			
			var body=document.body,
			elem=jQuery("<"+nodeName+">").appendTo(body),
			display=elem.css("display");			
			
			elem.remove();			
			
			// If the simple way fails,
			// get element's real default display by attaching it to a temp iframe
			if(display==="none"||display===""){
				
				// No iframe to use yet, so create it
				if(!iframe){
					
					iframe=document.createElement("iframe");					
					iframe.frameBorder=iframe.width=iframe.height=0;					
					
				}

				
				body.appendChild(iframe);				
				
				// Create a cacheable copy of the iframe document on first call.
				// IE and Opera will allow us to reuse the iframeDoc without
				// re-writing the fake HTML
				// document to it; WebKit & Firefox won't allow reusing the iframe
				// document.
				if(!iframeDoc||!iframe.createElement){
					
					iframeDoc=(iframe.contentWindow||iframe.contentDocument).document;					
					iframeDoc.write((document.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>");					
					iframeDoc.close();					
					
				}

				
				elem=iframeDoc.createElement(nodeName);				
				
				iframeDoc.body.appendChild(elem);				
				
				display=jQuery.css(elem,"display");				
				
				body.removeChild(iframe);				
				
			}

			
			// Store the correct default display
			elemdisplay[nodeName]=display;			
			
		}

		
		return elemdisplay[nodeName];		
		
	}//#s13129-e13189
	
	
	//1============================================================================================	
	
	
	var rtable=/^t(?:able|d|h)$/i,
	rroot=/^(?:body|html)$/i;	
	
	
	//1============================================================================================	
	
	
	if("getBoundingClientRect" in document.documentElement){
		
		jQuery.fn.offset=function (options){
			
			var elem=this[0],box;			
			
			if(options){
				
				return this.each(function (i){
					
					jQuery.offset.setOffset(this,options,i);					
					
				});				
				
			}

			
			if(!elem||!elem.ownerDocument){
				
				return null;				
				
			}

			
			if(elem===elem.ownerDocument.body){
				
				return jQuery.offset.bodyOffset(elem);				
				
			}

			
			try{
				
				box=elem.getBoundingClientRect();				
				
			}catch(e){
				
			}

			
			var doc=elem.ownerDocument,
			docElem=doc.documentElement;			
			
			// Make sure we're not dealing with a disconnected DOM node
			if(!box||!jQuery.contains(docElem,elem)){
				
				return box?{
					top:box.top,left:box.left
				}
:{
					top:0,left:0
				};				
				
			}

			
			var body=doc.body,
			win=getWindow(doc),
			clientTop=docElem.clientTop||body.clientTop||0,
			clientLeft=docElem.clientLeft||body.clientLeft||0,
			scrollTop=win.pageYOffset||jQuery.support.boxModel&&docElem.scrollTop||body.scrollTop,
			scrollLeft=win.pageXOffset||jQuery.support.boxModel&&docElem.scrollLeft||body.scrollLeft,
			top=box.top+scrollTop-clientTop,
			left=box.left+scrollLeft-clientLeft;			
			
			return {
				top:top,left:left
			};			
			
		};		
		
		
	}else {
		
		jQuery.fn.offset=function (options){
			
			var elem=this[0];			
			
			if(options){
				
				return this.each(function (i){
					
					jQuery.offset.setOffset(this,options,i);					
					
				});				
				
			}

			
			if(!elem||!elem.ownerDocument){
				
				return null;				
				
			}

			
			if(elem===elem.ownerDocument.body){
				
				return jQuery.offset.bodyOffset(elem);				
				
			}

			
			jQuery.offset.initialize();			
			
			var computedStyle,
			offsetParent=elem.offsetParent,
			prevOffsetParent=elem,
			doc=elem.ownerDocument,
			docElem=doc.documentElement,
			body=doc.body,
			defaultView=doc.defaultView,
			prevComputedStyle=defaultView?defaultView.getComputedStyle(elem,null):elem.currentStyle,
			top=elem.offsetTop,
			left=elem.offsetLeft;			
			
			while((elem=elem.parentNode)&&elem!==body&&elem!==docElem){
				
				if(jQuery.offset.supportsFixedPosition&&prevComputedStyle.position==="fixed"){
					
					break;					
					
				}

				
				computedStyle=defaultView?defaultView.getComputedStyle(elem,null):elem.currentStyle;				
				top-=elem.scrollTop;				
				left-=elem.scrollLeft;				
				
				if(elem===offsetParent){
					
					top+=elem.offsetTop;					
					left+=elem.offsetLeft;					
					
					if(jQuery.offset.doesNotAddBorder&&!(jQuery.offset.doesAddBorderForTableAndCells&&rtable.test(elem.nodeName))){
						
						top+=parseFloat(computedStyle.borderTopWidth)||0;						
						left+=parseFloat(computedStyle.borderLeftWidth)||0;						
						
					}

					
					prevOffsetParent=offsetParent;					
					offsetParent=elem.offsetParent;					
					
				}

				
				if(jQuery.offset.subtractsBorderForOverflowNotVisible&&computedStyle.overflow!=="visible"){
					
					top+=parseFloat(computedStyle.borderTopWidth)||0;					
					left+=parseFloat(computedStyle.borderLeftWidth)||0;					
					
				}

				
				prevComputedStyle=computedStyle;				
				
			}

			
			if(prevComputedStyle.position==="relative"||prevComputedStyle.position==="static"){
				
				top+=body.offsetTop;				
				left+=body.offsetLeft;				
				
			}

			
			if(jQuery.offset.supportsFixedPosition&&prevComputedStyle.position==="fixed"){
				
				top+=Math.max(docElem.scrollTop,body.scrollTop);				
				left+=Math.max(docElem.scrollLeft,body.scrollLeft);				
				
			}

			
			return {
				top:top,left:left
			};			
			
		};		
		
	}
	
	
	//1============================================================================================	

	
	jQuery.offset={//#s13391-e13522
		
		initialize:function (){
			
			var body=document.body,container=document.createElement("div"),innerDiv,checkDiv,table,td,bodyMarginTop=parseFloat(jQuery.css(body,"marginTop"))||0,
			html="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";			
			
			jQuery.extend(container.style,{
				position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"
			});			
			
			container.innerHTML=html;			
			body.insertBefore(container,body.firstChild);			
			innerDiv=container.firstChild;			
			checkDiv=innerDiv.firstChild;			
			td=innerDiv.nextSibling.firstChild.firstChild;			
			
			this.doesNotAddBorder=(checkDiv.offsetTop!==5);			
			this.doesAddBorderForTableAndCells=(td.offsetTop===5);			
			
			checkDiv.style.position="fixed";			
			checkDiv.style.top="20px";			
			
			// safari subtracts parent border width here which is 5px
			this.supportsFixedPosition=(checkDiv.offsetTop===20||checkDiv.offsetTop===15);			
			checkDiv.style.position=checkDiv.style.top="";			
			
			innerDiv.style.overflow="hidden";			
			innerDiv.style.position="relative";			
			
			this.subtractsBorderForOverflowNotVisible=(checkDiv.offsetTop===-5);			
			
			this.doesNotIncludeMarginInBodyOffset=(body.offsetTop!==bodyMarginTop);			
			
			body.removeChild(container);			
			jQuery.offset.initialize=jQuery.noop;			
			
		},
		
		bodyOffset:function (body){
			
			var top=body.offsetTop,
			left=body.offsetLeft;			
			
			jQuery.offset.initialize();			
			
			if(jQuery.offset.doesNotIncludeMarginInBodyOffset){
				
				top+=parseFloat(jQuery.css(body,"marginTop"))||0;				
				left+=parseFloat(jQuery.css(body,"marginLeft"))||0;				
				
			}

			
			return {
				top:top,left:left
			};			
			
		},
		
		setOffset:function (elem,options,i){
			
			var position=jQuery.css(elem,"position");			
			
			// set position first, in-case top/left are set even on static elem
			if(position==="static"){
				
				elem.style.position="relative";				
				
			}

			
			var curElem=jQuery(elem),
			curOffset=curElem.offset(),
			curCSSTop=jQuery.css(elem,"top"),
			curCSSLeft=jQuery.css(elem,"left"),
			calculatePosition=(position==="absolute"||position==="fixed")&&jQuery.inArray("auto",[curCSSTop,curCSSLeft])>-1,
			props={
				
			},curPosition={
				
			},curTop,curLeft;			
			
			// need to be able to calculate position if either top or left is auto
			// and position is either absolute or fixed
			if(calculatePosition){
				
				curPosition=curElem.position();				
				curTop=curPosition.top;				
				curLeft=curPosition.left;				
				
			}else {
				
				curTop=parseFloat(curCSSTop)||0;				
				curLeft=parseFloat(curCSSLeft)||0;				
				
			}

			
			if(jQuery.isFunction(options)){
				
				options=options.call(elem,i,curOffset);				
				
			}

			
			if(options.top!=null){
				
				props.top=(options.top-curOffset.top)+curTop;				
				
			}

			if(options.left!=null){
				
				props.left=(options.left-curOffset.left)+curLeft;				
				
			}

			
			if("using" in options){
				
				options.using.call(elem,props);				
				
			}else {
				
				curElem.css(props);				
				
			}
			
		}
		
	};//#s13391-e13522	
	
	
	//1============================================================================================	
	
	
	jQuery.fn.extend({//#s13528-e13588
		
		//获取匹配元素中第一个元素的当前坐标，相对于offset parent的坐标。( offset parent指离该元素最近的而且被定位过的祖先元素 ) 
		position:function (){
			
			if(!this[0]){
				
				return null;				
				
			}

			
			var elem=this[0],
			
			// Get *real* offsetParent
			offsetParent=this.offsetParent(),
			
			// Get correct offsets
			offset=this.offset(),
			parentOffset=rroot.test(offsetParent[0].nodeName)?{
				top:0,left:0
			}
:offsetParent.offset();			
			
			// Subtract element margins
			// note: when an element has margin: auto the offsetLeft and marginLeft
			// are the same in Safari causing offset.left to incorrectly be 0
			offset.top-=parseFloat(jQuery.css(elem,"marginTop"))||0;			
			offset.left-=parseFloat(jQuery.css(elem,"marginLeft"))||0;			
			
			// Add offsetParent borders
			parentOffset.top+=parseFloat(jQuery.css(offsetParent[0],"borderTopWidth"))||0;			
			parentOffset.left+=parseFloat(jQuery.css(offsetParent[0],"borderLeftWidth"))||0;			
			
			// Subtract the two offsets
			return {
				
				top:offset.top-parentOffset.top,
				left:offset.left-parentOffset.left
				
			};			
			
		},
		
		//返回最近的被定过位的祖先元素。（祖先元素指该元素的上级元素，即包着它的外层元素）
		offsetParent:function (){
			
			return this.map(function (){
				
				var offsetParent=this.offsetParent||document.body;				
				while(offsetParent&&(!rroot.test(offsetParent.nodeName)&&jQuery.css(offsetParent,"position")==="static")){
					
					offsetParent=offsetParent.offsetParent;					
					
				}

				return offsetParent;				
				
			});			
			
		}
		
	});//#s13528-e13588
	
	
	//1============================================================================================		
	

	/**
	 * 这里为jQuery增加两个非常有用的方法：
	 * (1)scrollLeft方法：为匹配的元素集合中获取或设置第一个元素的滚动条的水平位置。
	 * 示例：(1.1)获取：$("div.demo").scrollLeft();(1.2)设置：$("div.demo").scrollLeft(300);
	 * 
	 * (2)scrollTop方法：为匹配的元素集合中获取第一个元素的滚动条的垂直位置。
	 * 示例：(2.1)获取：$("div.demo").scrollTop();(2.2)设置：$("div.demo").scrollTop(300);
	 */
	// Create scrollLeft and scrollTop methods
	jQuery.each(["Left","Top"],function (i,name){//#s13595-e13648
		
		var method="scroll"+name;		
		
		jQuery.fn[method]=function (val){
			
			var elem,win;			
			
			if(val===undefined){
				
				elem=this[0];				
				
				if(!elem){
					
					return null;					
					
				}

				
				win=getWindow(elem);				
				
				// Return the scroll offset
				return win?("pageXOffset" in win)?win[i?"pageYOffset":"pageXOffset"]:
				jQuery.support.boxModel&&win.document.documentElement[method]||
				win.document.body[method]:
				elem[method];				
				
			}

			
			// Set the scroll offset
			return this.each(function (){
				
				win=getWindow(this);				
				
				if(win){
					
					win.scrollTo(
					!i?val:jQuery(win).scrollLeft(),
					i?val:jQuery(win).scrollTop()
					);					
					
					
				}else {
					
					this[method]=val;					
					
				}
				
			});			
			
		};		
		
	});	//#s13595-e13648
	
	
	//1============================================================================================	
	
	
	function getWindow(elem){//#s13654-e13662
		
		return jQuery.isWindow(elem)?
		elem:
		elem.nodeType===9?
		elem.defaultView||elem.parentWindow:
		false;		
		
	}//#s13654-e13662
	
	
	//1============================================================================================	
	

	/**
	 * 这里为jQuery增加多个非常有用的方法：
	 * (1)innerHeight方法：为匹配的元素集合中获取第一个元素的当前计算高度值,包括padding，但是不包括border。
	 * (2)innerWidth方法：为匹配的元素集合中获取第一个元素的当前计算宽度值,包括padding，但是不包括border。
	 * (3)outerHeight方法：为匹配的元素集合中获取第一个元素的当前计算高度值,包括padding，border和选择性的margin。
	 * (4)outerWidth方法：为匹配的元素集合中获取第一个元素的当前计算宽度值,包括padding，border。
	 */
	// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth
	// methods
	jQuery.each(["Height","Width"],function (i,name){//#s13670-e13761
		
		
		var type=name.toLowerCase();		
		
		// innerHeight and innerWidth
		jQuery.fn["inner"+name]=function (){
			
			var elem=this[0];			
			return elem&&elem.style?
			parseFloat(jQuery.css(elem,type,"padding")):
			null;			
			
		};		
		
		// outerHeight and outerWidth
		jQuery.fn["outer"+name]=function (margin){
			
			var elem=this[0];			
			return elem&&elem.style?
			parseFloat(jQuery.css(elem,type,margin?"margin":"border")):
			null;			
			
		};		
		
		jQuery.fn[type]=function (size){
			
			// Get window width or height
			var elem=this[0];			
			if(!elem){
				
				return size==null?null:this;				
				
			}

			
			if(jQuery.isFunction(size)){
				
				return this.each(function (i){
					
					var self=jQuery(this);					
					self[type](size.call(this,i,self[type]()));					
					
				});				
				
			}

			
			if(jQuery.isWindow(elem)){
				
				// Everyone else use document.documentElement or document.body
				// depending on Quirks vs Standards mode
				// 3rd condition allows Nokia support, as it supports the docElem
				// prop but not CSS1Compat
				var docElemProp=elem.document.documentElement["client"+name];				
				return elem.document.compatMode==="CSS1Compat"&&docElemProp||
				elem.document.body["client"+name]||docElemProp;				
				
				// Get document width or height
				
			}else if(elem.nodeType===9){
				
				// Either scroll[Width/Height] or offset[Width/Height], whichever is
				// greater
				return Math.max(
				elem.documentElement["client"+name],
				elem.body["scroll"+name],elem.documentElement["scroll"+name],
				elem.body["offset"+name],elem.documentElement["offset"+name]
				);				
				
				// Get or set width or height on the element
				
			}else if(size===undefined){
				
				var orig=jQuery.css(elem,type),
				ret=parseFloat(orig);				
				
				return jQuery.isNaN(ret)?orig:ret;				
				
				// Set the width or height on the element (default to pixels if value is
				// unitless)
				
			}else {
				
				return this.css(type,typeof size==="string"?size:size+"px");				
				
			}
			
		};		
		
		
	});//#s13670-e13761
	
	
	//1============================================================================================		
	
	
	/**
	 * 将jQuery设置为Global全局对象。
	 * 由此可见，$其实是jQuery的别名（或者说引用）而已，缩短到只有一个字符，太牛叉了。
	 * 通过参考此方式，如果$已经被别的js框架占用（如Prototype框架也使用了$），
	 * 可以继续增加别的jQuery的别名。
	 * 示例：
	 * <pre>
	 * 	if(!window.j$){
	 * 		window.j$=jQuery;
	 * 	}
	 * </pre>
	 */
	window.jQuery=window.$=jQuery;	// 将jQuery设置为Global全局对象。
	
	
	//1============================================================================================	
	
})(window);//注意：这里的window是作为一个实数被传入，将其传入供jQuery调用





///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 * 收集的一些jQuery插件：
 */
/*
(1)ZTree：http://www.baby666.cn/v3/main.php#_zTreeInfo
 */
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////






///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 收集其他经典js代码、教程或工具
*/
/*
(1)推荐两个js在线调试器,在线调试javascript的工具：A：第一个：jsFiddle，网址：http://jsfiddle.net/。		B：第二个：JS Bin，网址：http://jsbin.com/
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

